RosettaCodeData/Task/Chat-server/Python/chat-server.py

79 lines
2.2 KiB
Python

#!/usr/bin/env python
import socket
import thread
import time
HOST = ""
PORT = 4004
def accept(conn):
"""
Call the inner func in a thread so as not to block. Wait for a
name to be entered from the given connection. Once a name is
entered, set the connection to non-blocking and add the user to
the users dict.
"""
def threaded():
while True:
conn.send("Please enter your name: ")
try:
name = conn.recv(1024).strip()
except socket.error:
continue
if name in users:
conn.send("Name entered is already in use.\n")
elif name:
conn.setblocking(False)
users[name] = conn
broadcast(name, "+++ %s arrived +++" % name)
break
thread.start_new_thread(threaded, ())
def broadcast(name, message):
"""
Send a message to all users from the given name.
"""
print message
for to_name, conn in users.items():
if to_name != name:
try:
conn.send(message + "\n")
except socket.error:
pass
# Set up the server socket.
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.setblocking(False)
server.bind((HOST, PORT))
server.listen(1)
print "Listening on %s" % ("%s:%s" % server.getsockname())
# Main event loop.
users = {}
while True:
try:
# Accept new connections.
while True:
try:
conn, addr = server.accept()
except socket.error:
break
accept(conn)
# Read from connections.
for name, conn in users.items():
try:
message = conn.recv(1024)
except socket.error:
continue
if not message:
# Empty string is given on disconnect.
del users[name]
broadcast(name, "--- %s leaves ---" % name)
else:
broadcast(name, "%s> %s" % (name, message.strip()))
time.sleep(.1)
except (SystemExit, KeyboardInterrupt):
break