Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 尝试对非套接字的对象执行操作(尝试了大量修复)_Python_Windows_Sockets - Fatal编程技术网

Python 尝试对非套接字的对象执行操作(尝试了大量修复)

Python 尝试对非套接字的对象执行操作(尝试了大量修复),python,windows,sockets,Python,Windows,Sockets,在你说这是一个副本之前,我已经看了很多关于这个的文章,仍然无法修复它。 我正在制作一个非常基本的聊天客户端和服务器python程序 但是,通过我的客户端连接后,服务器控制台上会显示“已连接”,但聊天室控制台上会立即断开连接,错误为“OSError:[WinError 10038]尝试对非连接的对象执行操作 插座 聊天 从中选择: Windows上的文件对象是不可接受的,但套接字是可接受的。在…上 在Windows中,基础select()函数由WinSock提供 并且不处理非源文件的文件描述符 来

在你说这是一个副本之前,我已经看了很多关于这个的文章,仍然无法修复它。 我正在制作一个非常基本的聊天客户端和服务器python程序

但是,通过我的客户端连接后,服务器控制台上会显示“已连接”,但聊天室控制台上会立即断开连接,错误为“OSError:[WinError 10038]尝试对非连接的对象执行操作 插座

聊天


中选择

Windows上的文件对象是不可接受的,但套接字是可接受的。在…上 在Windows中,基础select()函数由WinSock提供 并且不处理非源文件的文件描述符 来自WinSock

这排除了使用
sys.stdin
的可能性

备选方案

  • 使用(无需修改代码)
  • 创建一个等待sys.stdin的线程(比如)
  • 走完整的Windows路线并使用
  • 使用一些将这些细节抽象出来的库,我喜欢但还没有在python中使用它

另一件事:不要在无限循环中使用超时为零的
select
。这种忙碌的等待真的没有效率。相反,忽略超时以使
选择
块,直到描述符就绪。

对于Python 3,
ctypes.pythonapi.\u PyOS\u siginEvent()
返回为
SIGINT
设置的Windows事件的句柄。将其附加到句柄数组中,以允许调用
WaitForMultipleObjects
可被Ctrl+C中断。Python 3的
\u winapi.WaitForMultipleObjects
会为您执行此操作,但前提是不要要求它等待所有对象,因为要求等待Ctrl+C是没有意义的。
def chat_client():
    if(len(sys.argv) not in (3, 4)):
        print("Usage: python chat_client.py <hostname> <port> <optional-username>\n")
        sys.exit()

    host = sys.argv[1]
    port = int(sys.argv[2])
    username = ""
    if len(sys.argv) == 4: 
        username = sys.argv[3]
    else:
        username = "Guest"

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)

    # Connect to remote host
    try:
        s.connect((host, port))
    except:
        print("Unable to connect")
        sys.exit()

    print("Connected to remote host. You can start sending messages")
    print("***   Press Control-C to log off   ***\n")
    sys.stdout.write("[" + username + "] ")
    sys.stdout.flush()

    while True:
        socket_list = [sys.stdin, s]

        try:
            # Get the list sockets which are readable
            ready_to_read, ready_to_write, in_error = select.select(socket_list, [], [])
        except KeyboardInterrupt:
            system("clear")
            sys.stdout.write("\nYou have logged off\n")
            sys.stdout.flush()
            sys.exit()
HOST = ""
SOCKET_LIST = []
RECV_BUFFER = 4096
PORT = 9009
CONVERSATION = ""

def chat_server():
    global CONVERSATION
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind((HOST, PORT))
    server_socket.listen(10)

    # Add server socket object to the list of readable connections
    SOCKET_LIST.append(server_socket)

    print("Chat server started on port " + str(PORT))

    while True:
        try:
            # Get the list sockets which are ready to be read through select
            # 4th arg, time_out = 0 : poll and never block
            ready_to_read, ready_to_write, in_error = select.select(SOCKET_LIST, [], [], 0)

            for sock in ready_to_read:
                # A new connection request recieved
                if sock == server_socket:
                    sockfd, addr = server_socket.accept()
                    SOCKET_LIST.append(sockfd)
                    print("Client (%s, %s) connected" % addr)

                    broadcast(server_socket, sockfd, "[%s, %s] entered our chatting room\n" % addr)
                # A message from a client, not a new connection
                else:
                    # Process data recieved from client
                    try:
                        # Recieving data from socket
                        data = sock.recv(RECV_BUFFER)
                        if data:
                            # there is something in the socket
                            # broadcast(server_socket, sock, "\r" + '[' + str(sock.getpeername()) + '] ' + data) # old
                            broadcast(server_socket, sock, "\r" + data)
                        else:
                            # Remove the socket that's broken
                            if sock in SOCKET_LIST:
                                SOCKET_LIST.remove(sock)

                            # at this stage, no data probably means the connection has been broken
                            broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
                    except:
                        broadcast(server_socket, sock, "Client (%s, %s) is offline\n" % addr)
                        continue
        except KeyboardInterrupt:
            server_socket.close()
            sys.exit()

    server_socket.close()


# broadcast chat messages to all connected clients
def broadcast(server_socket, sock, message):
    for socket in SOCKET_LIST:
        # send the message only to peer
        if socket != server_socket and socket != sock:
            try:
                socket.send(message)
            except:
                # Broken socket connection
                socket.close()
                # Broken socket, remove it
                if socket in SOCKET_LIST:
                    SOCKET_LIST.remove(socket)

if __name__ == "__main__":
    sys.exit(chat_server())