I am working on a simple chat server, storing the connected clients in a dict
. I set blocking to false, but it appears everything is holding up while polling for user input.
I can connect with one client, the server shows that it will receive and broadcast a message successfully, but when another client tried to connect, it cannot until the first user "shakes it loose" by submitting another message.
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()
I am using the following script in another terminal to connect.
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()
I think the problem is in how I'm declaring my socket, though I'm not positive I'm using threads properly either. Thanks!
The issue is that accept
returns a new socket and, "initially all sockets are in blocking mode." (from https://docs.python.org/2/library/socket.html). So you need to add a conn.setblocking(0)
right after the accept call returns.