views:

4028

answers:

3

Here is source code for multithreaed server and client in python.

PROBLEM:

In the code client and server closes connection after the job is finished. I want to keep the connections alive and send more data over the same connections to avoid overhead of closing and opening sockets everytime.

What is the best way to do this? I am new to socket programming and threading.

Thanks in advance!!!

Following code is from : http://www.devshed.com/c/a/Python/Basic-Threading-in-Python/1/

import pickle
import socket
import threading

# We'll pickle a list of numbers:
someList = [ 1, 2, 7, 9, 0 ]
pickledList = pickle.dumps ( someList )

# Our thread class:
class ClientThread ( threading.Thread ):

   # Override Thread's __init__ method to accept the parameters needed:
   def __init__ ( self, channel, details ):

      self.channel = channel
      self.details = details
      threading.Thread.__init__ ( self )

   def run ( self ):

      print 'Received connection:', self.details [ 0 ]
      self.channel.send ( pickledList )
      for x in xrange ( 10 ):
         print self.channel.recv ( 1024 )
      self.channel.close()
      print 'Closed connection:', self.details [ 0 ]

# Set up the server:
server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
server.bind ( ( '', 2727 ) )
server.listen ( 5 )

# Have the server serve "forever":
while True:
   channel, details = server.accept()
   ClientThread ( channel, details ).start()

---------------------------------------------------

import pickle
import socket
import threading

# Here's our thread:
class ConnectionThread ( threading.Thread ):

   def run ( self ):

      # Connect to the server:
      client = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
      client.connect ( ( 'localhost', 2727 ) )

      # Retrieve and unpickle the list object:
      print pickle.loads ( client.recv ( 1024 ) )

      # Send some messages:
      for x in xrange ( 10 ):
         client.send ( 'Hey. ' + str ( x ) + '\n' )

      # Close the connection
      client.close()

# Let's spawn a few threads:
for x in xrange ( 5 ):
   ConnectionThread().start()
+2  A: 

I'm not sure I understand the question, but don't call close() if you don't want to close the connection...

sth
+6  A: 

Spawning a new thread for every connection is a really bad design choice. What happens if you get hit by a lot of connections?

In fact, using threads to wait for network IO is not worth it. Your program gets really complex and you get absolutely no benefit since waiting for network in threads won't make you wait faster. You only lose by using threads in this case.

The following text is from python documentation:

There are only two ways to have a program on a single processor do “more than one thing at a time.” Multi-threaded programming is the simplest and most popular way to do it, but there is another very different technique, that lets you have nearly all the advantages of multi-threading, without actually using multiple threads. It’s really only practical if your program is largely I/O bound. If your program is processor bound, then pre-emptive scheduled threads are probably what you really need. Network servers are rarely processor bound, however.

And if it is a processor bound server case. you could always leave another process/thread to do the processor part. Continuing:

If your operating system supports the select system call in its I/O library (and nearly all do), then you can use it to juggle multiple communication channels at once; doing other work while your I/O is taking place in the “background.” Although this strategy can seem strange and complex, especially at first, it is in many ways easier to understand and control than multi-threaded programming.

So instead of using threads, use non-blocking input/output: collect the sockets in a list and use an event loop with select.select to know which socket has data to read. Do that in a single thread.

You could choose a python asynchronous networking framework like twisted to do that for you. That will save you a lot of headaches. Twisted's code has been improved for years, and covers some corner cases you'll take time to master.

EDIT: Any existing async IO libraries (like Twisted) are python code. You could have written it yourself, but it has already been written for you. I don't see why you wouldn't use one of those libraries and write your own worst code instead, since you are a beginner. Networing IO is hard to get right.

nosklo
How to do asynchronous networking without using twisted or any other library ?Please suggest.
TheMachineCharmer
@david: I just did so in the 3rd paragraph of my question.
nosklo
@david: You can't do anything without using libraries. Everything is a library. From a certain point of view, python itself is a library. You can always copy parts or the entire twisted code inside your application and pretend you wrote it. Twisted is pure python.
nosklo
@david: in other words, twisted is the code you could have written yourself. Only it has already been written for you. I don't see why you wouldn't use it (or any other library for async IO) and write your own *worst* code instead.
nosklo
@nosklo: Thanks for suggestion but isnt there any very simple example to understand how actually asynch n/w works in python.
TheMachineCharmer
@david: twisted code itself is an example.
nosklo
@nosklo: I'll download and study it.Thank you very much.
TheMachineCharmer
A: 

For an example of a client the keeps a TCP connection open and uses a familiar protocol, look at the source of the telnetlib module. (sorry, someone else will have to answer your threading questions.)

An example of a server that keeps a TCP connection open is in the source for the SocketServer module (any standard Python installation includes the source).

gimel