gSocket.py

Go to the documentation of this file.
00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2004
00004 #                                     by
00005 #                        The Board of Trustees of the
00006 #                     Leland Stanford Junior University.
00007 #                            All rights reserved.
00008 #
00009 
00010 
00011 __facility__ = "Online"
00012 __abstract__ = "Socket class"
00013 __author__   = "Amedeo Perazzo <perazzo@slac.stanford.edu> SLAC - GLAST I&T/Online"
00014 __date__     = ("$Date: 2005/09/22 00:29:31 $").split(' ')[1]
00015 __version__  = "$Revision: 1.2 $"
00016 __release__  = "$Name: HEAD $"
00017 __credits__  = "SLAC"
00018 
00019 import LICOS.copyright_SLAC
00020 
00021 import socket
00022 import threading
00023 
00024 class ConnectState:
00025   Disconnected = 0
00026   Waiting      = 1
00027   Connected    = 2
00028 
00029 class Socket(object):
00030   TIMEOUT = 5
00031 
00032   def __init__(self, portnumber):
00033     self.__port = portnumber
00034     self.__sock = None
00035     self.__host = None
00036     self.__lock = threading.Lock()
00037 
00038   def connect(self, host=None, connectors=1):
00039     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
00040     sock.settimeout(self.TIMEOUT)  # TMOs are not handled correctly
00041     try:
00042       if host is None:
00043         # listening socket
00044         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
00045         sock.settimeout(self.TIMEOUT)  # TMOs are not handled correctly
00046         sock.bind(('', port))
00047         sock.listen(connectors)
00048         self.__sock,addr = sock.accept()
00049       else:
00050         # external socket
00051         self.__sock = sock
00052         self.__sock.connect((host, self.__port))
00053         self.__host = host
00054           
00055     except socket.error, msg:
00056       self.disconnect()
00057       raise RuntimeError, \
00058             'gSocket: unable to connect to %s on port %d: %s' \
00059             %(host, self.__port, str(msg))
00060     ss = 2*1024*1024
00061     self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, ss)
00062 
00063   def disconnect(self):
00064     if self.isConnected():
00065       self.__sock.close()
00066       self.__sock = None
00067 
00068   def isConnected(self):
00069     return (self.__sock is not None)
00070 
00071   def socket(self):
00072     return self.__sock
00073 
00074   def setSocket(self, sock):
00075     self.__sock = sock
00076 
00077   def port(self):
00078     return self.__port
00079 
00080   def setPort(self, port):
00081     self.__port = port
00082 
00083   def lock(self):
00084     self.__lock.acquire()
00085 
00086   def release(self):
00087     self.__lock.release()
00088 
00089   def gettimeout(self):
00090     return self.__sock.gettimeout()
00091 
00092   def settimeout(self, seconds):
00093     self.__sock.settimeout(seconds)
00094 
00095   def send(self, packet):
00096     return self.__sock.send(packet)
00097 
00098   def recv(self, size):
00099     return self.__sock.recv(size)
00100 
00101   def sendall(self, packet):
00102     return self.__sock.sendall(packet)
00103 
00104   def recvall(self, size):
00105     # The following is not supported on Windows, at least.
00106     # return self.__sock.recv(size, socket.MSG_WAITALL)
00107 
00108     data = ''
00109     remaining = size
00110     sock = self.__sock
00111     while remaining > 0:
00112       received = sock.recv(remaining)
00113       reclen = len(received)
00114       if reclen == 0: return received
00115       remaining -= reclen
00116       data += received
00117     return data
00118 
00119   def purge(self):
00120     """!\brief Purge all stale data out of the socket.
00121     """
00122     max  = 64*1024
00123     sock = self.__sock
00124     tmo  = sock.gettimeout()
00125     sock.settimeout(0.1)
00126     received = ''
00127     size = 0
00128     while size != 0:
00129       try:
00130         received = sock.recv(max)
00131       except socket.error, e:
00132         if str(e) != "timed out":  raise # Throw away "timed out" exceptions
00133       size = len(received)
00134 
00135     sock.settimeout(tmo)
00136     
00137 class ReconnectingSocket(Socket):
00138   def __init__(self, port, host):
00139     Socket.__init__(self, port)
00140     self.__name = name
00141     self.__host = host
00142     
00143   def send(self, packet):
00144     self.lock()
00145     rv = super(ReconnectingSocket, self).send(packet)
00146     self.release()
00147     return rv
00148 
00149   def recv(self, size):
00150     self.lock()
00151     rv = super(ReconnectingSocket, self).recv(size)
00152     self.release()
00153     return rv
00154 
00155   def sendall(self, packet):
00156     self.lock()
00157     rv = super(ReconnectingSocket, self).sendall(packet)
00158     self.release()
00159     return rv
00160 
00161   def recvall(self, packet):
00162     self.lock()
00163     rv = super(ReconnectingSocket, self).recvall(packet)
00164     self.release()
00165     return rv
00166 
00167   def connect(self, host=None):
00168     """!\brief connect
00169 
00170     Connect to the socket
00171     """
00172     self.__connection_state = ConnectState.Waiting
00173     self.__tries = 0
00174     self.__host = host
00175     self.__connect()
00176     
00177   def disconnect(self):
00178     """!\brief disconnected
00179 
00180     """
00181     self.__disconnect()
00182 
00183   def timedout(self):
00184     """!\brief timedout
00185     """
00186     self.__disconnect()
00187 
00188   def __disconnect(self):
00189     # disconnect from the server
00190     super(ReconnectingSocket, self).disconnect()
00191     # deal with the outcome of disconnecting
00192     self.__connection_notthere()
00193     
00194   def __connection_notthere(self):
00195     # Do this once...
00196     if self.__connection_state == ConnectState.Connected:
00197       log.error("Socket disconnected, trying to reconnect" )
00198       self.__connection_state = ConnectState.Waiting
00199       self.__connect()
00200     
00201   def __connect(self):
00202     # spawn the connecting thread in the background
00203     connecthdlr = threading.Thread(None, self.__connection_handler, 'ConnectHandler',())
00204     connecthdlr.setDaemon(True)
00205     connecthdlr.start()
00206 
00207   def __connection_handler(self):
00208     while (True):
00209       try:
00210         super(ReconnectingSocket, self).connect(self.__host)
00211         log.info("Socket is now connected")
00212         self.__connection_state = ConnectState.Connected
00213         self.__tries = 0
00214         break
00215       except RuntimeError, msg:
00216         if self.__tries == 0:
00217           log.error(msg)
00218         self.__tries += 1
00219         state = self.__connection_state
00220         if state == ConnectState.Disconnected: break
00221         time.sleep(3)
00222     
00223     
00224 # EOF

Generated on Thu Apr 27 20:52:41 2006 for LICOS L02-01-00 by doxygen 1.4.6-NO