[Tutor] Network programming

Kent Johnson kent_johnson at skillsoft.com
Fri Sep 10 03:44:47 CEST 2004


Johan,

It looks to me like your program will get stuck in the inner while loop. 
There is no way inside this loop to get a new value for indata or outdata.

There are two approaches you could use to solve your problem - either put 
the two sides of the transfer into separate threads, or use some kind of 
polling to look for data available on either socket.

The thread approach usually uses three threads:
- a master thread that listens to the server socket and accepts the 
incoming connection. It then opens the forwarding socket and spawns two 
forwarding threads.
- the forwarding threads read from one socket and write to another. They 
are symmetric - one thread reads from socket A and writes to socket B; the 
other thread reads from socket B and writes to socket A.

Each thread uses blocking I/O - the master thread blocks on 
socket.accept(); the forwarding threads block on socket.recv().

A simple example that uses the treaded approach to do something similar to 
what you want to do is here: 
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/114642
In this case the Pinhole class is the master thread; when it gets a 
connection it creates two PipeThreads to do the reading and writing.


The polling approach uses non-blocking I/O. In it's crudest form its loop 
looks like this:
forever:
   if data available on socket A:
     read from socket A
     write to socket B
   if data available on socket B:
     read from socket B
     write to socket A
   sleep for a bit

This is crude because it is either unresponsive (if the sleep is long) or 
wasteful of CPU (if the sleep is short and there is not much to do). It 
might be fine for a simple use with just one connection, though.

The Python asyncore and asynchat modules use a more sophisticated version 
of this; instead of sleeping, they use a system call that blocks until 
there is activity on any of the sockets it is watching. This is very 
efficient, as the polling loop only wakes up when there is something for it 
to do. Medusa <http://www.nightmare.com/medusa/index.html> and Twisted 
<http://www.twistedmatrix.com/> are two servers that are based on this 
approach. It can be more efficient for large numbers of connections because 
it doesn't have to create a thread for each one.

asyncore and asynchat hide the actual polling loop from you. You interact 
with them by defining callback methods that get called when data is 
available or when a channel is available for writing. This tutorial is a 
good introduction to this approach. The proxy server at the end is similar 
to what you are trying to do. http://www.nightmare.com/medusa/programming.html

Medusa includes a chat server which is also similar to your application.

I hope this helps get you on the right track!
Kent

At 10:14 AM 9/9/2004 +0200, Johan Geldenhuys wrote:
>I still have trouble when I want to send data out as soon as it comes in 
>from one side.
>My server listens and accepts the calls and then builds the client 
>connection to the destination. Please see if you can assist.
>
>Thanks
>
>Johan
>####################################################
>
># we have an incoming socket connect
>                     newConn, addr = self._serverSocket.accept()
>                     self.log('Connection received from: %s:%s' % addr)
>
>                  #while connection is active on server:
>                  while 1:
>                             #self._ne1_id = '1234'
>                             #self._ne2_id = '1111'
>
>                             indata = newConn.recv(8192)
>                             self.log('First Data received from LCT:' + 
> `indata`)
>
>                             if '\xff' in indata:
>                              continue
>
>                           if '\x01' in indata:
>                              continue
>
>                            #Look for string of 1234 in indata:
>                              if indata[0:4] == self._ne1_id:
>                                 self.log('indata 0:4 is:' + `indata[0:4]`)
>                                 self.sock = socket(AF_INET, SOCK_STREAM)
>
>                             #connect to this destination if the string is 
> 1234
>                             self.sock.connect((self._ne1_ip, 
> self._ne1_port)) # This is previously defined
>                                self.log('Connection established to NE1: 
> %s:%i' % (self._ne1_ip, self._ne1_port))
>                                outdata = self.sock.recv(8192)
>                                #when connection to destination is up:
>                             while 1:
>                                    if indata:
>                                    self.sock.send(indata)
>                                     self.log('indata send to NE, line 
> 106: ' + `indata`)
>
>                                   # If break sequence is received from 
> server side, close the client connection
>                                        if '\x11' in indata:
>                                      self.log('Break character received')
>                                      break
>                                        self.sock.close()
>                                     self.log('connection to NE1 now closed')
>
>                                    if oudata:
>                                       newConn.send(outdata)
>                                       self.log('Data from NE:' + `outdata`)
>###########################################################
>
>
>
>
>
>
>
>
>
>
>
>On Tue, 2004-09-07 at 14:58, Kent Johnson wrote:
>>
>>
>>We might be better able to help if you post your code.
>>
>>Here is a list of HTTP proxy servers written in Python, you might find
>>something helpful there:
>><http://xhaus.com/alan/python/proxies.html>http://xhaus.com/alan/python/proxies.html
>>
>>Kent
>>
>>At 02:19 PM 9/6/2004 +0200, Johan Geldenhuys wrote:
>> >Hi,
>> >
>> >I am new to Python and would like to know more about network programming
>> >in particilar.
>> >
>> >I have a script that sets up a socket server and must wait for incoming
>> >connections. Once a call has been accepted, it must make another socket
>> >connection to a destination.
>> >
>> >Now, I want to let these two "talk" to each other. Once the server
>> >receives data it must be send out to the destination and when the
>> >destination has data, it must be send out to the connection that made the
>> >first call to the server.
>> >
>> >Does anybody have any examples or tips on how I can let this happen. My
>> >calls work for the first batch of data and then when new data is received,
>> >the calls break.
>> >
>> >Thanks
>> >
>> >--
>> >        Johan Geldenhuys
>> >Access Telecommunication Systems
>> >  Mail to: johan at accesstel.co.za
>> >--
>> >This message has been scanned for viruses and
>> >dangerous content by 
>> <<http://www.azitech.co.za>http://www.azitech.co.za>Azitech, and is
>> >believed to be clean.
>> >_______________________________________________
>> >Tutor maillist  -  Tutor at python.org
>> ><http://mail.python.org/mailman/listinfo/tutor>http://mail.python.org/ma 
>> ilman/listinfo/tutor
>
>
>
>
>
>--
>        Johan Geldenhuys
>Access Telecommunication Systems
>  Mail to: johan at accesstel.co.za
>
>--
>This message has been scanned for viruses and
>dangerous content by <http://www.azitech.co.za>Azitech, and is
>believed to be clean.



More information about the Tutor mailing list