Opening sockets on multiple ports

Alain Désilets alain.desilets at nrc.ca
Mon Nov 12 23:00:07 CET 2001


I'm trying to implement a 2-way communication link between a client and
a server. By 2-way, I mean that both the client and the server can
initiate transactions. So in fact, the "client" is only a client in the
sense that it is responsible for initiating the connection with the
"server" during the hand-shaking part of the protocol. But after that,
both sides can initiate transactions (this is done in separate threads
obviously).

My approach is to implement a non-blocking server using the SocketServer
module. The client and server communicate through a pair of sockets, the
TO_SERVER and FROM_SERVER sockets. Those are used  for transactions that
are initiated by the client and by the server respectively.

Attached are two small pieces of code for the client and server parts.

My problem is that I can't seem to be able to open two sockets on two
different ports. For example, if I run those scripts in separate
windows, I get:

****** in the client window *********
E:\VoiceCode\VCode.TCP_IP\Mediator>python socket_client_pylist.py

-- ToServerThread: AF_INET=2, SOCK_STREAM=1, HOST=alaindes,
TO_SERVER_PORT=50007

-- TO_SERVER Connection {'_sock': <socket object, fd=76, family=2,
type=1, protocol=0>} opened
-- FromServerThread: AF_INET=2, SOCK_STREAM=1, HOST=alaindes,
FROM_SERVER_PORT=50008
Traceback (innermost last):
  File "socket_client_pylist.py", line 47, in ?
    fsChannel = FromServerThread()
  File "socket_client_pylist.py", line 32, in __init__
    aSocket.connect(HOST, FROM_SERVER_PORT)
  File "<string>", line 1, in connect
socket.error: (10061, 'winsock error')

****** in the server window *********
E:\VoiceCode\VCode.TCP_IP\Mediator>python socket_server_pylist.py
... TO_SERVER Connection {'_sock': <socket object, fd=92, family=2,
type=1, protocol=0>}: Starting handler


In other words, the first connection (on the TO_SERVER port) opens
correctly, but the second one (on the FROM_SERVER port) fails.

Note that if I set both TO_SERVER_PORT and FROM_SERVER_PORT to the same
port number (on both client and server sides), then I don't get this
problem, i.e. I am able to open both connections. But then messages for
client-initiated and server-initiated transactions get mixed together
(not shown in this code, but I have tried it and that's what happens).

Note also that everything happens in separate threads on both the client
and server sides.

On the client side, the two sockets are started by two separate threads.

On the server side, the two SocketServers are running in separate
threads. In addition, the handlers used to process a new connection are
also spawned as separate threads (i.e. I use ThreadingTCPServer).

Can anyone pull me out of the mud here?

Thanks


--
Alain Désilets

Agent de recherche
Conseil National de Recherches du Canada

Research Officer
National Research Council of Canad

-------------- next part --------------
import SocketServer
import threading

# Port for transactions initiated by the client
TO_SERVER_PORT = 50007

# Port for transactions initiated by the server
FROM_SERVER_PORT = 50008

#
# This handler is invoked when a new TO_SERVER socket is opened
#
class ToServerHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        f = self.request.makefile()
        print '... TO_SERVER Connection %s: Starting handler' % self.request.__dict__        

#
# This handler is invoked when a new FROM_SERVER socket is opened
#
class FromServerHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        f = self.request.makefile()
        print '... FROM_SERVER Connection %s: Starting handler' % self.id
        
#
# This thread listens for new connections on the TO_SERVER port
#
class ToServerServer(threading.Thread):
   
   def __init__(self):
       self.server = SocketServer.ThreadingTCPServer(("", TO_SERVER_PORT), ToServerHandler)
       
   def run(self):
      self.server.serve_forever()       

#
# This thread listens for new connections on the FROM_SERVER port
#
class FromServerServer(threading.Thread):
   
   def __init__(self):
       self.server = SocketServer.ThreadingTCPServer(("", FROM_SERVER_PORT), FromServerHandler)
       
   def run(self):
      self.server.serve_forever()       


#
# Start 2 threads, each listening for new connections on the TO_SERVER and
# FROM_SERVER ports respectively
#
def serve_non_blocking():

    # TO_SERVER thread
    tsServer = ToServerServer()
    tsServer.run()

    # FROM_SERVER thread
    fsServer = FromServerServer()
    fsServer.run()

    
#
# This third thread simulates a busy server
#
class DoStuffThread(threading.Thread):
    def run(self):
        """Simulate a very busy server"""

        while 1:
            x = 1
#            print 'x=%s' % x


if __name__ == '__main__':

    # Simulate busy server
    doer = DoStuffThread()
    doer.start()

    # Listen for connections on the TO_SERVER and FROM_SERVER ports
    serve_non_blocking()


-------------- next part --------------
from socket import *
import threading

# Port for transactions initiated by client
TO_SERVER_PORT = 50007

# Port for transactions initiated by server
FROM_SERVER_PORT = 50008

HOST = gethostname()

#
# This thread opens a new connection on the server's TO_SERVER port
#
class ToServerThread(threading.Thread):

   def __init__(self):
      print '-- ToServerThread: AF_INET=%s, SOCK_STREAM=%s, HOST=%s, TO_SERVER_PORT=%s' % (AF_INET, SOCK_STREAM, HOST, TO_SERVER_PORT)      
      aSocket = socket(AF_INET, SOCK_STREAM)
      aSocket.connect(HOST, TO_SERVER_PORT)
      print '-- TO_SERVER Connection %s opened' % repr(aSocket.__dict__)

   def run(self):
      pass
      
      

class FromServerThread(threading.Thread):
   def __init__(self):
      print '-- FromServerThread: AF_INET=%s, SOCK_STREAM=%s, HOST=%s, FROM_SERVER_PORT=%s' % (AF_INET, SOCK_STREAM, HOST, FROM_SERVER_PORT)
      aSocket = socket(AF_INET, SOCK_STREAM)
      aSocket.connect(HOST, FROM_SERVER_PORT)      
      print '-- FROM_SERVER connection %s opened' % repr(aSocket.__dict__)

   def run(self):
      pass


   
if __name__ == "__main__":
    #
    # Initiate connection to the server
    #
    tsChannel = ToServerThread()
    tsChannel.run()
    
    fsChannel = FromServerThread()
    fsChannel.run()  
    
    #
    # In the mean time, do some stuff in the main thread to simulate a busy
    # client.
    #
    ii = 0
    while 1:
#        print "I'm a busy client: %s" % ii
        ii = ii + 1





More information about the Python-list mailing list