Hi guys,
I am trying to create a python chat server. So far, it has been going well but a problem has come up with threading.
The threading for incoming connections works fine (in the listen_and_accept function). Since I would like to be able to type in commands in the server terminal window, I though I would start two threads, one calling the command_line function and one to call the listen_and_accept funtion (which in turn would create threads for the incoming connections).
For some reason this. doesn't work. Could it be the indented threading? (Output from running the server (not much) is below). All the rest works fine so far...
Edit: Output is below. I know the code must look pretty stupid to you, but I am just getting started (a few days), any of-topic tips would also be greatly appreciated!
Thanks!
Code:
#!/usr/bin/env python
#########################################################
# Chat (client or server)
#########################################################
#
# Author: Oliver Stollmann
# Date: 17.11.09
#
import thread, sys, time
import socket as s
print "---------------------------------------------------"
# Check for valid call
if sys.argv.__len__() == 3:
type = 'SERVER'
elif sys.argv.__len__() == 4:
type = 'CLIENT'
else:
sys.exit("Error! Usage: %s server:[name port], client:[nick_name host port]" % sys.argv[0])
class chat_server:
def __init__(self, server_name, server_port, socket=None):
'''Constructor'''
# Chat server name
self._SERVER_NAME = server_name
# Chat server port
self._SERVER_PORT = int(server_port)
# Chat server IP
self._SERVER_IP = s.gethostbyname(s.gethostname())
# Socket: new/existing?
if socket is None:
self.socket = s.socket(s.AF_INET, s.SOCK_STREAM)
else:
self.socket = socket
# clients[[socket, ip, id, name]]
self.clients = []
# Bind to socket
self.bind(self._SERVER_IP, self._SERVER_PORT)
# Server commands thread
thread.start_new_thread(self.command_line, ('a','b')) # <---------- THIS ISNT THE PROBLEM (I think)
# Listen thread
thread.start_new_thread(self.listen_and_accept,('a', 'b')) # <---------- THIS IS THE PROBLEM (I think)
def command_line(a,b,c):
input = raw_input('> ')
print input
def bind(self, host, port):
'''Socket bind'''
try:
self.socket.bind((host, port))
except s.error:
sys.exit("Error! Could not bind.")
def listen_and_accept(self, a):
self.socket.listen(5)
'''listen for accept() requests'''
print "Listening (" + str(self._SERVER_IP) + ":" + str(self._SERVER_PORT) + ")..."
while True:
c_socket, c_address = self.socket.accept()
c_ip = c_address[0]
c_id = c_address[1]
c_name = c_socket.recv(1024)
self.add_client(c_socket, c_ip, c_id, c_name)
print 'New user: ' + str(c_name) + '@' + str(c_ip)
thread.start_new_thread(self.handle, (c_socket, c_ip, c_id, c_name))
def handle(self, c_socket, c_ip, c_id, c_name):
'''handle client'''
print 'New thread for user: ' + str(c_name) + '@' + str(c_ip)
# time.sleep(2)
# thread.exit()
# print 'Thread closed!'
while True:
data = c_socket.recv(1024)
if data == 'quit()':
c_socket.send('GoodBye!')
print 'User', str(c_ip), 'hast left the chat!'
thread.exit()
else:
self.send(c_ip, c_id, c_name, data)
def add_client(self, c_socket, c_ip, c_id, c_name):
'''add client'''
new_client = [c_socket, c_ip, c_id, c_name]
self.clients.append(new_client)
def remove_client(self, c_ip, c_id, c_name):
'''remove client'''
t = False
for i in range(self.clients.__len__()):
if self.clients[i][1] == c_ip and self.clients[i][2] == c_id and self.clients[i][3] == c_name:
self.clients.remove(self.clients[i])
t = True
return t
def check_client(self, c_ip, c_id, c_name):
'''check client'''
for i in range(self.clients.__len__()):
if self.clients[i][1] == c_ip and self.clients[i][2] == c_id and self.clients[i][3] == c_name:
c = client[i]
return c
def send(self, c_ip, c_id, c_name, data):
'''Send message'''
for client in self.clients:
if client[1] != c_ip or client[2] != c_id or client[3] != c_name:
# message body
client[0].send(data)
print 'Message from', str(c_ip), 'sent:', str(data)
def details(self):
'''Server details'''
print "Chat Server details:"
print " name:", self._SERVER_NAME
print " IP:", self._SERVER_IP
print " port", self._SERVER_PORT
def quit(self):
self.socket.close()
server1 = chat_server(sys.argv[1], sys.argv[2])
################
# output:
#
# mbp1:final mbp1$ python chat_server.py test 2408
# ---------------------------------------------------
# mbp1:final mbp1$