[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