Python Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesPython Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
AT&T devCentral & BlackBerry(r) Webcast Series: BlackBerry and GPS -Build Location Awareness into your BlackBerry Applications, July 10th-1:00PM EST. Register Today!
  #1  
Old March 1st, 2004, 04:39 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Threaded Server

I've got a simple threaded server but I don't know how to manage my threads so the server can send the input of one client to another.

Code:
#!/usr/bin/env python

import socket
import sys

import threading

class serveClient(threading.Thread):
	def __init__(self, client, addr, tid):
		threading.Thread.__init__(self)
		self.client = client
		self.addr = addr
		self.tid = tid
		print '%s connected' % (self.addr[0])
		
	def run(self):
		while True:
			input = self.client.recv(1)
			if not input:
				break
			print '%s says: %s' % (self.addr[0], input)
		
		self.client.close()
		
class acceptClient(threading.Thread):		
	def run(self):
		server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		port = int(sys.argv[1])
		server.bind(('', port))
		server.listen(5)
		for tid in range(2):
			(client, addr) = server.accept()
			thread = serveClient(client, addr, tid)
			thread.start()
			
			

if __name__ == '__main__':	

	server = acceptClient()
	server.start()


Reply With Quote
  #2  
Old March 2nd, 2004, 06:12 PM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
Just a few thoughts:
You could keep track of your serveClient objects in a list.

I guess you would need a queue to stack the incomming messages (you can get multiple incommings). If you assume all clients talk to each other, you could periodically send the messages out to them. You could just step through each object and send all the messages out en-mass, working on a copy of the queue to allow the clients to send in more messages. You will need locks on the queue to prevent problems with simultaneous access.

No idea how it would perform tho - you have a lot to handle (e.g. blocking, exceptions, dropped conections)

But I think twisted already have a chat type server

Grim
__________________
*** Experimental Python Markup CGI V2 ***

Reply With Quote
  #3  
Old March 3rd, 2004, 01:46 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
So for the threads list:

Code:
threadlist = []      
thread = serveClient(client, addr, tid)
theadlist.append(thread)
threadlist[tid].start()


I don't think I approached this in the right way. It's going to take a bit more thinking to get it working right. I'll post back later.

Reply With Quote
  #4  
Old March 3rd, 2004, 03:00 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
I've got something a bit different now but I'm still having a few problems

Code:
import socket
import sys

import threading

messages = []
clientlist = []

class clientReceive(threading.Thread):
	def __init__(self, client, addr, tid):
		threading.Thread.__init__(self)
		self.client = client
		self.addr = addr
		self.tid = tid
		
	def run(self):
		global messages		
		while True:
			msg = self.client.recv(1)
			if msg == 0:
				break
			else:
				messages.append(str(self.tid) + msg)
		self.client.close()
		
class clientSend(threading.Thread):
	def run(self):
		global messages
		global clientlist
		
		if messages:
			for msg in messages:
				current = msg[0] # Not used atm.
				del msg[0]
				for client in clientlist:
					client.client.send(char(msg))
				

if __name__ == '__main__':	
	server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	port = int(sys.argv[1])
	server.bind(('', port))
	server.listen(5)
	
	thread = clientSend()
	thread.start()
	
	for tid in range(2):
		(client, addr) = server.accept()
		print '%s connected' % (addr[0])
		thread = clientReceive(client, addr, tid)
           thread.start()
		clientlist.append(thread)


For some reason run() in clientSend doesn't ever send info. From what I can tell, it never even makes it past the 'if messages: ' bit.

Reply With Quote
  #5  
Old March 3rd, 2004, 05:29 PM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
Xx,
The clientSend thread will terminate as soon as the message list is empty. At the beginning the list is empty so it terminates straight away.

That thread need to stay alive - maybe a while loop in the thread.
Code:
while OK_to_run:
    If messages:
         .......
    #and put thread on hold until something happens

Last edited by Grim Archon : March 3rd, 2004 at 05:34 PM.

Reply With Quote
  #6  
Old March 3rd, 2004, 05:42 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
OMG! I knew it would be something silly like that! Thanks .

Reply With Quote
  #7  
Old March 4th, 2004, 10:43 AM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
I have most of the multithreading stuff fixed now but I'm not sure how to implement proper message sending/receiving. At the moment I'm only passing chars (1 byte) around. How do I accommodate for abitrary length messages?

EDIT: btw, are globals the only way to communicate in between threads?

Thanks in advance .

Last edited by XxChris : March 4th, 2004 at 10:57 AM.

Reply With Quote
  #8  
Old March 4th, 2004, 12:43 PM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
self.client.recv(1024) will recieve upto 1024 bytes but returns as soon as there is no data left to read or the maximum is reached.

The Queue module should help as it is designed for inter-thread communication. You will probably need one per connection for receiving message but you could even have a second for sending. The advantage here is that it handles the locking for you

You will probably need to handle the empty/full exceptions.

Does your sender terminate too soon?

Grim

Reply With Quote
  #9  
Old March 4th, 2004, 01:41 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Thanks, I will look into that module. I'm going to continue to mess with this for a while until I'm satisfied for the moment. I'll then post it here.

Reply With Quote
  #10  
Old March 5th, 2004, 02:23 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Ok all the send stuff is working properly, but I'm having trouble getting the server to quit prematurely. What is a good way to get all the threads to quit? I've tryed a few ways without much luck .

Reply With Quote
  #11  
Old March 5th, 2004, 06:25 PM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
I'm sure there are other (read 'better') ways but try replacing the While True: with While global_run_variable:
Then you can use the global variable to tell the threads to finish. If you declare the name as global in the threading class then any of your threads could change it to False. As the only time the variable changes state will be to go from True to False there is no worry about racing values. Having more than one thread doing the same thing only results in the value going to False.

WRT to your earlier question - threads share the same global namespace so there is really no other way for them to communicate other than complicated pipes or sockets. This is why locks were created for situations where multiple threads influence globally accessable values. The Queue module wraps global standard objects and hides the complexity for you.

You could/should use the join() method to make sure things have shut down before the main thread moves on to other things.

If this idea is not satisfactory then you could consider re-writting the code to use select and then you can enforce time out conditions.

Grim

Reply With Quote
  #12  
Old March 5th, 2004, 10:59 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
I already tryed the global_run idea but if a socket is blocking on a recv() it doesn't turn out too well .

Reply With Quote
  #13  
Old March 6th, 2004, 06:12 AM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
If you are running Python 2.3 then the socket module supports new functions:

socket.setdefaulttimeout( timeout)
if you use setdefaulttimeout(0.1) then the recv should timeout within 100 msec.

Also you can set the socket object to non-blocking:
socket_object.setblocking( False)
and set timeout values
socket_object.settimeout( 0.1)

That will allow your loops to continue.
Note: if the recv and send functions return without doing anything they raise a socket error exception.

Plenty to experiment with.


Grim

Reply With Quote
  #14  
Old March 6th, 2004, 09:26 AM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Ahh cool thanks .

Reply With Quote
  #15  
Old March 6th, 2004, 04:29 PM
XxChris XxChris is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2003
Posts: 217 XxChris User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Grrr, another problem. This one just doesn't make sense to me. I run threading.currentThread() and I get the thread object of the thread that created the thread that is calling it (currentThread()).

EDIT: Turns out if I don't place it in the class constructor it works . Anybody know why this happens?

Last edited by XxChris : March 6th, 2004 at 04:35 PM.

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesPython Programming > Threaded Server


Thread Tools  Search this Thread 
Search this Thread:

Advanced