# # Describe a connection over a socket. # # This class is intended to be apdapted into IEndpoint interface import socket from zope import interface import errno import select from interfaces import endpoint from zope import component from interfaces.message import Debug @interface.implementer(endpoint.IConnection) class SocketConnection(object): """ Define a connected element (serial, network…) """ def __init__(self, configuration): self.port = int(configuration["port"]) self.host = configuration["host"] def connect(self) -> None: """ Connect """ self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.connect((self.host, self.port)) component.handle(Debug("Connected to the socket")) def read(self) -> str: """ Read from the connection and return the bytes. Return None if there is nothing to read (non-blocking) Raise an exception if disconnected """ # check the socket for reading in non-blocking mode read_socket, _, _ = select.select([self.s], [], [], 0.0) if read_socket == []: return try: recv = self.s.recv(1024) if recv == b"": # We should be able to read something, but got nothing. # Reset the socket raise RuntimeError("socket connection broken") return recv except socket.error as e: err = e.args[0] if err == errno.EAGAIN or err == errno.EWOULDBLOCK: return None raise e def write(self, content:str) -> None: """ Write into the connection. Raise an exception if disconnected """ self.s.sendall(content + bytes("\n", "utf-8"))