为什么这个 socket.recv() 会阻塞?

Why is this socket.recv() blocking?

我正在开发一个简单的聊天服务器,将连接的客户端存储在 dict 中。我将阻止设置为 false,但在轮询用户输入时似乎一切都停止了。

我可以连接到一个客户端,服务器显示它将成功接收和广播一条消息,但是当另一个客户端尝试连接时,它不能连接,直到第一个用户 "shakes it loose" 提交另一条消息。

server.py

import socket
import time
import threading

def handle_new_connection(connection):
    def handle_t():
        while 1:
            connection.send("Please enter desired username:  ")
            try:
                username = connection.recv(256)
                if username in connections:
                    connection.send("Username taken.")
                elif username:
                    connections[username] = connection
                    connection.send('Welcome to chat, ' + username)
                    print (username + ' has entered chat.')
                    return
            except socket.error as e:
                print e
                break
    handle = threading.Thread(target=handle_t, args=())
    handle.daemon = False
    handle.start()

def broadcast(sender, message):
    print 'Broadcasting:  ' + message
    for username, conn in connections.items():
        if username != sender:
            try:
                conn.send(''.join((sender, ": ", message)).encode('utf-8'))
            except socket.error as e:
                print e
                pass

serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serverSocket.setblocking(False)
serverSocket.bind(('', 55555))
serverSocket.listen(5)

connections = {}

print 'Booting Server...'

while 1:
    try:
        while 1:
            try:
                conn, addr = serverSocket.accept()
                print ("New Incoming Connection")
            except socket.error as e:
                break
            handle_new_connection(conn)

        for user, conn in connections.items():
            print 'polling for ' + user
            try:
                raw_data = conn.recv(256) # <-- HANGING HERE
                data = raw_data.decode('utf-8')
            except socket.error as e:
                continue

            if data:
                print data
                broadcast(user, data)
            else:
                del connections[user]
                broadcast(user, 'left chat. ' + str(len(connections)) + ' users.')
                print user + " left chat. " + str(len(connections)) + " users."
    except (SystemExit, KeyboardInterrupt):
        break

print 'Closing Server Socket...'
serverSocket.close()    
exit()

我正在另一个终端中使用以下脚本进行连接。

client.py

import socket
import threading

def create_sender():
    def sender_t():
        while 1:
            try:
                while 1:
                    try:
                        data = raw_input()
                        clientsocket.send(data.encode('utf-8'))
                    except socket.error as e:
                        break
                    except (SystemExit, KeyboardInterrupt):
                        break
            except (SystemExit, KeyboardInterrupt):
                break

    send = threading.Thread(target=sender_t, args=())
    send.start()

clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('', 55555))
clientsocket.setblocking(False)
print 'Connected to server.'

create_sender()
while 1:
    try:
        while 1:
            try:
                msg = clientsocket.recv(256).decode('utf-8')
                print msg
            except socket.error as e:
                break

    except (SystemExit, KeyboardInterrupt):
        break

clientsocket.close()

我认为问题出在我声明套接字的方式上,尽管我也不确定我是否正确使用了线程。谢谢!

问题是 accept returns 一个新套接字和 "initially all sockets are in blocking mode."(来自 https://docs.python.org/2/library/socket.html)。所以你需要在接受调用 returns.

之后添加一个 conn.setblocking(0)