为什么这个 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)
我正在开发一个简单的聊天服务器,将连接的客户端存储在 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)