Package ViewerFramework :: Module comm
[hide private]
[frames] | no frames]

Source Code for Module ViewerFramework.comm

  1  ############################################################################# 
  2  # 
  3  # Author: Michel F. SANNER 
  4  # 
  5  # Copyright: M. Sanner TSRI 2000 
  6  # 
  7  ############################################################################# 
  8  # 
  9  # $Header: /opt/cvs/python/packages/share1.5/ViewerFramework/comm.py,v 1.2 2004/09/17 02:09:05 sanner Exp $ 
 10  # 
 11  # $Id: comm.py,v 1.2 2004/09/17 02:09:05 sanner Exp $ 
 12  # 
 13   
 14   
 15  """ 
 16  COMM module 
 17   
 18  Author: Michel F. Sanner 
 19  Date: Oct 11 2000 
 20   
 21  This module implements the Comm class that provides bi-directional communication over sockets. The Comm object provides server functionality, accepting connections from multiple clients (each client is handled by a separate thread).  the comm object also provides client side functionality, allowing a Comm object to connect to an existing server. 
 22   
 23  A - Server side 
 24  After a Comm object has been created, the startServer method can be called to 
 25  create a socket (self.serverSocket) and find a free port to which this socket 
 26  will be bound. The port is stored in self.port 
 27   
 28  By calling the acceptClients(func, maxConnections) one can allow the server to accept connection from clients. 'func' will be called for each message sreceived from clients. FIXME: calling func should probably set a lock. 
 29  acceptClients works in its own thread. When a client connects, a new thread is started to handle input from this client (listenToClient()) and the client is added to the Comm's clients dictionary. 
 30   
 31  The client dictionary uses the client's name as a key and stores the socket and the address created by accept. 
 32   
 33  hangupClient(name, client) can be called to terminate a connection with a specific client. 
 34   
 35  sendToClients(message) can be used to send a string to all connected clients 
 36   
 37  B - Client side 
 38   
 39  A comm object can be used to connect to a running server using the connectToServer(self, host, port, func). host cane be a host name or an IP address (as string). If the connection is successful a new thread is started to listen to the server and 'func' will be called with all messages comming from that server. 
 40   
 41  disconnectFromServer(self, clientSocket) can be called to disconnect fropm a server. 'clientSocket' can be a socket or a  
 42  """ 
 43  import sys, time 
 44  from socket import * 
 45  import thread, types 
 46   
47 -class Comm:
48
49 - def __init__(self):
50 self.verbose = 1 # set to 0 to get rid of printing 51 52 # server related members 53 self.clients = {} # dictionary of clients, 54 # key is the host name+address bound to the socket 55 # on the other end of the connection 56 # value is (conn, addr) tuple 57 self.port = None # port used by server to accept connections 58 self.serverSocket = None # socket used by server to accpet conenctions 59 self.maxConnections = 5 # maximum number of conenctions allowed 60 61 # client related members 62 self.serverSockets = {} # dictionary of servers, key is the server's
63 # name, value is the socket created for this 64 # connection 65
66 - def getPort(self, socket, base=50000):
67 """find the first free port above base""" 68 port = base 69 while(1): 70 try: 71 socket.bind( ( '', port)) 72 return port 73 except: 74 import traceback 75 traceback.print_exc() 76 port = port + 1 77 print port
78 ## 79 ## server side
80 - def startServer(self, port=None):
81 self.serverSocket = s = socket(AF_INET, SOCK_STREAM) 82 if port is None: 83 self.port = self.getPort(s) 84 else: 85 self.port = port
86
87 - def acceptClients(self, func, maxConnections=5):
88 self.maxConnections = maxConnections 89 self.serverSocket.listen(maxConnections) 90 if self.verbose: 91 print "server ready, listening to port ", self.port 92 while 1: 93 conn, addr = self.serverSocket.accept() 94 name = gethostbyaddr(conn.getpeername()[0])[0] + str(addr[1]) 95 self.clients[name] = ( conn, addr ) 96 if self.verbose: 97 print 'Connected by', name, '\n' 98 thread.start_new(self.listenToClient, (name, conn, func))
99
100 - def listenToClient(self, name, client, func):
101 while (1): 102 i = 0 103 data = client.recv(1024) 104 if len(data)==0: 105 if self.verbose: 106 print 'Connection closed by client' 107 self.hangupClient(client) 108 return 109 func(name, data)
110
111 - def hangupClient(self, client):
112 if type(client) == types.StringType: 113 cl = self.clients[client][0] 114 else: 115 cl = client 116 client = None 117 for key, value in self.clients.items(): 118 if value[0]==cl: 119 client = key 120 break 121 if client is None: 122 raise ValueError, "client not found" 123 124 cl.close() 125 del self.clients[client]
126
127 - def sendToClients(self, message):
128 """send a messaqe to all clients""" 129 for c in self.clients.values(): 130 c[0].send(message)
131
132 - def getClients(self):
133 """send a messaqe to all clients""" 134 return self.clients.keys()
135 136 ## 137 ## client side
138 - def connectToServer(self, host, port, func):
139 """become a client of a server specified using host and port, 140 func will be called to handle messages from server 141 """ 142 host = gethostbyname(host) 143 serverSocket = socket(AF_INET, SOCK_STREAM) 144 serverSocket.connect( ( host, port)) 145 name = gethostbyaddr(serverSocket.getpeername()[0])[0]+str(port) 146 self.serverSockets[name] = serverSocket 147 thread.start_new(self.listenToServer, (name, serverSocket, func))
148
149 - def listenToServer(self, name, client, func):
150 while (1): 151 i = 0 152 data = client.recv(1024) 153 if len(data)==0: 154 print 'Connection closed by server' 155 self.disconnectFromServer(client) 156 return 157 func(name, data)
158
159 - def disconnectFromServer(self, server):
160 if type(server) == types.StringType: 161 cl = self.serverSockets[server] 162 else: 163 cl = server 164 server = None 165 for key, values in self.serverSockets.items(): 166 if values==cl: 167 server = key 168 break 169 if server is None: 170 raise ValueError, "server not found" 171 cl.shutdown(2) 172 cl.close() 173 del self.serverSockets[server]
174
175 - def getServers(self):
176 """send a messaqe to all servers""" 177 return self.serverSockets.keys()
178 179 180 if __name__ == '__main__': 181 com = Comm() 182 com.startServer() 183 #com.acceptClients() 184
185 - def foo1(client, data):
186 print 'client %s sent> %s'%(client,data)
187 188 thread.start_new(com.acceptClients, (foo1,)) 189
190 - def foo(server, data):
191 print 'server %s sent> %s'%(server,data)
192 193 #com.connectToServer('', 50008, foo) 194