You are on page 1of 5

# -*- coding: cp1252 -*-

import socket
""" This is a class that manages conections on the INET family
and uses only STREAM sockets.
NOTE: If a socket argument is passed, then this socket is used
as if it is connected already """
class connection:
def __init__( self, sock = None, address = None ):
# Class variables
self.__isServer = False
self.__isConnected = False
self.__isValid = False
self.__Messages = list()
self.__Buffer = str()
self.__Address = address
self.s = None
if( sock != None ):
if( not isinstance( sock, socket.socket ) ):
raise RuntimeError( "Invalid socket object" )
self.s = sock
self.s.setblocking( 0 )
self.__isConnected = True
self.__isValid = True
# Crea un nuevo objeto socket
# Parámetros: ninguno
# Retorno: ninguno
def __create_socket( self ):
self.s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
self.s.setblocking( 0 )
self.__isValid = True
# Regresa True si el objeto está conectado a otro proceso
# Parámetros: ninguno
# Retorno: boolean
def isConnected( self ):
return self.__isConnected
# Regresa True si el objeto es válido
# Parámetros: ninguno
# Retorno: boolean
def isValid( self ):
return self.__isValid
# Regresa la dirección a la que el objeto se encuentra conectado
# Parámetros: ninguno
# Retorno: tupla ( ip, puerto )
def getAddress( self ):
return self.__Address
# ******************************************************************
# SERVER OPERATIONS
# ******************************************************************
# Usado para un servidor, abre un puerto nuevo y escucha para
# conexiones entrantes
# Parámetros: Puerto
# Retorno: boolean
def make_server( self, port ):
# Delete any previous connection
if( self.__isConnected ):
self.s.close()
del self.s
self.__create_socket()
self.__isServer = False
self.__isConnected = False
# Try to bind the socket
try:
self.s.bind( ( '', port ) )
except socket.error:
raise RuntimeError( "Couldn't bind port " + str( port ) )
# Listen to the port
self.s.listen( 5 )
self.__isServer = True
self.__isConnected = True
#print "Listening to port", port
return True
# Acepta una conexión si existe una en la cola de conexiones. 'None'
# en caso contrario
# Parámetros: wait (esto significa que el socket espera hasta que haya
# alguna conexión en la cola)
# Retorno: Connection
def accept( self, wait = False ):
# Validate
if( not self.__isServer or not self.isValid() ):
raise RuntimeError( "Socket is not valid or is not a server" )
try:
if( wait ):
self.s.setblocking( 1 )
sock, addr = self.s.accept()
new_socket = connection( sock, addr )
if( wait ):
self.s.setblocking( 0 )
return new_socket
except socket.error:
#print "There are no connections"
return None
# ******************************************************************
# CLIENT OPERATIONS
# ******************************************************************
# Se conecta a un proceso por dirección y puerto
# Parámetros: dirección [str], puerto [int]
# Retorno: boolean
def connect( self, direction, port ):
# Validate
if( self.__isConnected ):
return False
if( not( isinstance( direction, str ) and isinstance( port, int ) ) ):
return False
self.__create_socket()
try:
self.s.setblocking( 1 )
self.s.connect( (direction, port) )
self.s.setblocking( 0 )
except socket.error:
return False
self.__isServer = False
self.__isConnected = True
return True

# ******************************************************************
# MESSAGE OPERATIONS
# ******************************************************************
# Actualiza el estado de la conexión y recibe mensajes nuevos.
# Parámetros: ninguno
# Retorno: boolean (True si se recibieron mensajes nuevos)
def update( self ):
# Validate
if( not self.__isConnected or not self.isValid() ):
return False
# Receive messages
try:
data = self.s.recv( 256 )
if( data == '' ):
self.__isConnected = False
self.__isValid = False
return False
except socket.error:
# There are no new messages
return False
# Add the message to the buffer, and check for new messages
self.__Buffer += data
# DEBUG:
# print "RECV BUFFER - ", self.__Buffer
while( len( self.__Buffer ) != 0 ):
start_index = self.__Buffer.find( '/' )
if( start_index == -1 ):
break
end_index = self.__Buffer.find( '/', start_index+1 )
if( end_index == -1 ):
break
# Check if we have a valid message (First char is "/")
# If not, clean that part
if( start_index == 0 ):
self.__Messages.append( self.__Buffer[start_index+1:end_index] )
else:
self.__Buffer = self.__Buffer[start_index+1:]
#DEBUG:
# print "CORRECTED BUFFER - ", self.__Buffer
continue
# Clean the buffer from the last message processed
self.__Buffer = self.__Buffer[end_index+1:]
# DEBUG
# print "PROCESSED BUFFER - ", self.__Buffer
return True
# Envía un mensaje de texto al proceso al cual el objeto se encuentra
# conectado.
# Parámetros: mensaje [str]
# Retorno: boolean
def send( self, message ):
# Validate
if( not self.__isConnected or not self.isValid() ):
# print "ERROR: Socket is not connected"
return False
if( len( message ) == 0 ):
return False
if( not( message[0] == '/' and message[-1] == '/' ) ):
# Format message
message = message.replace( '/', '' )
message = "/" + message + "/"
# Send the message
try:
total_sent = 0
while( total_sent < len(message) ):
sent = self.s.send( message[total_sent:] )
#DEBUG:
#print "<SENT>: ", sent
if( sent == 0 ):
# print "ERROR: Send message failed"
self.__isConnected = False
self.__isValid = False
return False
total_sent += sent
except socket.error:
# Connection has failed
# print "Send failed - Connection terminated"
self.__isValid = False
self.__isConnected = False
return False
return True
# Devuelve el mensaje más antiguo de la cola de mensajes, y lo
# elimina de la cola
# Parámetros: peek (True si no se quiere eliminar el mensaje de la cola)
# Retorno: mensaje [str]
def getMessage( self, peek = False ):
if( not self.isValid() or len( self.__Messages ) == 0 ):
return ""
if( peek ):
return self.__Messages
else:
msg = self.__Messages[0]
self.__Messages.remove( msg )
return msg

# Cierra la conexión con el proceso remoto


# Parámetros: ninguno
# Retorno: ninguno
def close( self ):
if( self.s != None ):
while( self.update() ):
pass
self.s.close()
self.s = None
self.__isConnected = False
self.__isServer = False
self.__isValid = False

You might also like