I am currently working on a school project where the assignment, among other things, is to set up a threaded server/client system. Each client in the system is supposed to be assigned its own thread on the server when connecting to it. In addition i would like the server to run other threads, one concerning input from the command line and another concerning broadcasting messages to all clients. However, I can't get this to run as i want to. It seems like the threads are blocking each other. I would like my program to take inputs from the command line, at the "same time" as the server listens to connected clients, and so on. I am new to python programming and multithreading, and allthough I think my idea is good, I'm not suprised my code doesn't work. Thing is I'm not exactly sure how I'm going to implement the message passing between the different threads. Nor am I sure exactly how to implement the resource lock commands properly. I'm going to post the code for my server file and my client file here, and I hope someone could help me with this. I think this actually should be two relative simple scripts. I have tried to comment on my code as good as possible to some extend. import select import socket import sys import threading import client class Server: #initializing server socket def __init__(self, event): self.host = 'localhost' self.port = 50000 self.backlog = 5 self.size = 1024 self.server = None self.server_running = False self.listen_threads = [] self.local_threads = [] self.clients = [] self.serverSocketLock = None self.cmdLock = None #here i have also declared some events for the command line input #and the receive function respectively, not sure if correct self.cmd_event = event self.socket_event = event def openSocket(self): #binding server to port try: self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.bind((self.host, self.port)) self.server.listen(5) print "Listening to port " + str(self.port) + "..." except socket.error, (value,message): if self.server: self.server.close() print "Could not open socket: " + message sys.exit(1) def run(self): self.openSocket() #making Rlocks for the socket and for the command line input self.serverSocketLock = threading.RLock() self.cmdLock = threading.RLock() #set blocking to non-blocking self.server.setblocking(0) #making two threads always running on the server, #one for the command line input, and one for broadcasting (sending) cmd_thread = threading.Thread(target=self.server_cmd) broadcast_thread = threading.Thread(target=self.broadcast,args=[self.clients]) cmd_thread.daemon = True broadcast_thread.daemon = True #append the threads to thread list self.local_threads.append(cmd_thread) self.local_threads.append(broadcast_thread) cmd_thread.start() broadcast_thread.start() self.server_running = True while self.server_running: #connecting to "knocking" clients try: c = client.Client(self.server.accept()) self.clients.append(c) print "Client " + str(c.address) + " connected" #making a thread for each clientn and appending it to client list listen_thread = threading.Thread(target=self.listenToClient,args=[c]) self.listen_threads.append(listen_thread) listen_thread.daemon = True listen_thread.start() #setting event "client has connected" self.socket_event.set() except socket.error, (value, message): continue #close threads self.server.close() print "Closing client threads" for c in self.listen_threads: c.join() def listenToClient(self, c): while self.server_running: #the idea here is to wait until the thread gets the message "client #has connected" self.socket_event.wait() #then clear the event immidiately... self.socket_event.clear() #and aquire the socket resource self.serverSocketLock.acquire() #the below is the receive thingy try: recvd_data = c.client.recv(self.size) if recvd_data == "" or recvd_data == "close\n": print "Client " + str(c.address) + (" disconnected...") self.socket_event.clear() self.serverSocketLock.release() return print recvd_data #I put these here to avoid locking the resource if no message #has been received self.socket_event.clear() self.serverSocketLock.release() except socket.error, (value, message): continue def server_cmd(self): #this is a simple command line utility while self.server_running: #got to have a smart way to make this work self.cmd_event.wait() self.cmd_event.clear() self.cmdLock.acquire() cmd = sys.stdin.readline() if cmd == "": continue if cmd == "close\n": print "Server shutting down..." self.server_running = False self.cmdLock.release() def broadcast(self, clients): while self.server_running: #this function will broadcast a message received from one #client, to all other clients, but i guess any thread #aspects applied to the above, will work here also try: send_data = sys.stdin.readline() if send_data == "": continue else: for c in clients: c.client.send(send_data) self.serverSocketLock.release() self.cmdLock.release() except socket.error, (value, message): continue if __name__ == "__main__": e = threading.Event() s = Server(e) s.run() And then the client file import select import socket import sys import server import threading class Client(threading.Thread): #initializing client socket def __init__(self,(client,address)): threading.Thread.__init__(self) self.client = client self.address = address self.size = 1024 self.client_running = False self.running_threads = [] self.ClientSocketLock = None def run(self): #connect to server self.client.connect(('localhost',50000)) #making a lock for the socket resource self.clientSocketLock = threading.Lock() self.client.setblocking(0) self.client_running = True #making two threads, one for receiving messages from server... listen = threading.Thread(target=self.listenToServer) #...and one for sending messages to server speak = threading.Thread(target=self.speakToServer) #not actually sure wat daemon means listen.daemon = True speak.daemon = True #appending the threads to the thread-list self.running_threads.append(listen) self.running_threads.append(speak) listen.start() speak.start() #this while-loop is just for avoiding the script terminating while self.client_running: dummy = 1 #closing the threads if the client goes down print "Client operating on its own" self.client.close() #close threads for t in self.running_threads: t.join() return #defining "listen"-function def listenToServer(self): while self.client_running: #here i acquire the socket to this function, but i realize I also #should have a message passing wait()-function or something #somewhere self.clientSocketLock.acquire() try: data_recvd = self.client.recv(self.size) print data_recvd except socket.error, (value,message): continue #releasing the socket resource self.clientSocketLock.release() #defining "speak"-function, doing much the same as for the above function def speakToServer(self): while self.client_running: self.clientSocketLock.acquire() try: send_data = sys.stdin.readline() if send_data == "close\n": print "Disconnecting..." self.client_running = False else: self.client.send(send_data) except socket.error, (value,message): continue self.clientSocketLock.release() if __name__ == "__main__": c = Client((socket.socket(socket.AF_INET, socket.SOCK_STREAM),'localhost')) c.run() I realize this is quite a few code lines for you to read through, but as I said, I think the concept and the script in it self should be quite simple to understand. It would be very much appriciated if someone could help me synchronize my threads in a proper way =) Thanks in advance ---Edit--- OK. So I now have simplified my code to just containing send and receive functions in both the server and the client modules. The clients connecting to the server gets their own threads, and the send and receive functions in both modules operetes in their own separate threads. This works like a charm, with the broadcast function in the server module echoing strings it gets from one client to all clients. So far so good! The next thing i want my script to do, is taking specific commands, i.e. "close", in the client module to shut down the client, and join all running threads in the thread list. Im using an event flag to notify the listenToServer and the main thread that the speakToServer thread has read the input "close". It seems like the main thread jumps out of its while loop and starts the for loop that is supposed to join the other threads. But here it hangs. It seems like the while loop in the listenToServer thread never stops even though server_running should be set to False when the event flag is set. I'm posting only the client module here, because I guess an answer to get these two threads to synchronize will relate to synchronizing more threads in both the client and the server module also. import select import socket import sys import server_bygg0203 import threading from time import sleep class Client(threading.Thread): #initializing client socket def __init__(self,(client,address)): threading.Thread.__init__(self) self.client = client self.address = address self.size = 1024 self.client_running = False self.running_threads = [] self.ClientSocketLock = None self.disconnected = threading.Event() def run(self): #connect to server self.client.connect(('localhost',50000)) #self.client.setblocking(0) self.client_running = True #making two threads, one for receiving messages from server... listen = threading.Thread(target=self.listenToServer) #...and one for sending messages to server speak = threading.Thread(target=self.speakToServer) #not actually sure what daemon means listen.daemon = True speak.daemon = True #appending the threads to the thread-list self.running_threads.append((listen,"listen")) self.running_threads.append((speak, "speak")) listen.start() speak.start() while self.client_running: #check if event is set, and if it is #set while statement to false if self.disconnected.isSet(): self.client_running = False #closing the threads if the client goes down print "Client operating on its own" self.client.shutdown(1) self.client.close() #close threads #the script hangs at the for-loop below, and #refuses to close the listen-thread (and possibly #also the speak thread, but it never gets that far) for t in self.running_threads: print "Waiting for " + t[1] + " to close..." t[0].join() self.disconnected.clear() return #defining "speak"-function def speakToServer(self): #sends strings to server while self.client_running: try: send_data = sys.stdin.readline() self.client.send(send_data) #I want the "close" command #to set an event flag, which is being read by all other threads, #and, at the same time set the while statement to false if send_data == "close\n": print "Disconnecting..." self.disconnected.set() self.client_running = False except socket.error, (value,message): continue return #defining "listen"-function def listenToServer(self): #receives strings from server while self.client_running: #check if event is set, and if it is #set while statement to false if self.disconnected.isSet(): self.client_running = False try: data_recvd = self.client.recv(self.size) print data_recvd except socket.error, (value,message): continue return if __name__ == "__main__": c = Client((socket.socket(socket.AF_INET, socket.SOCK_STREAM),'localhost')) c.run() Later on, when I get this server/client system up and running, I will use this system on some elevator models we have here on the lab, with each client receiving floor orders or "up" and "down" calls. The server will be running an distribution algorithm and updating the elevator queues on the clients that are most appropriate for the requested order. I realize it's a long way to go, but I guess one should just take one step at the time =) Hope someone has the time to look into this. Thanks in advance. Continue reading...