Conector API de Python IB WinError 10038

Conector API de Python IB WinError 10038

esto está codificado como 'connection.py' en la API de Interactive Brokers. Cuando se ejecuta, devuelve un error "Se intentó una operación en algo que no era un socket", en "buf = self.socket.recv(4096)". Intenté cambiar el valor pasado a recv a 7497, para que coincida con el puerto de Socket, pero recibo el mismo mensaje. Creo que puede ser un error de formato, pero soy demasiado nuevo en Python para saberlo con seguridad.

logger = logging.getLogger(__name__)


class Connection:
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.socket = None
        self.wrapper = None
        self.lock = threading.Lock()


    def connect(self):
        try:
            self.socket = socket.socket()
        #TODO: list the exceptions you want to catch
        except socket.error:
            if self.wrapper:
                self.wrapper.error(NO_VALID_ID, FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg())

        try:
            self.socket.connect((self.host, self.port))
        except socket.error:
            if self.wrapper:
                self.wrapper.error(NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg())

        self.socket.settimeout(1)   #non-blocking


    def disconnect(self):
        self.lock.acquire()
        try:
            if self.socket is not None:
                logger.debug("disconnecting")
                self.socket.close()
                self.socket = None
                logger.debug("disconnected")
                if self.wrapper:
                    self.wrapper.connectionClosed()
        finally:
            self.lock.release()


    def isConnected(self):
        return self.socket is not None


    def sendMsg(self, msg):

        logger.debug("acquiring lock")
        self.lock.acquire()
        logger.debug("acquired lock")
        if not self.isConnected():
            logger.debug("sendMsg attempted while not connected, releasing lock")
            self.lock.release()
            return 0
        try:
            nSent = self.socket.send(msg)
        except socket.error:
            logger.debug("exception from sendMsg %s", sys.exc_info())
            raise
        finally:
            logger.debug("releasing lock")
            self.lock.release()
            logger.debug("release lock")

        logger.debug("sendMsg: sent: %d", nSent)

        return nSent


    def _recvMsg(self):
        if not self.isConnected():
            logger.debug("recvMsg attempted while not connected, releasing lock")
            return b""
        try:
            buf = self.recvAllMsg()
            # receiving 0 bytes outside a timeout means the connection is either
            # closed or broken
            if len(buf) == 0:
                logger.debug("socket either closed or broken, disconnecting")
                self.disconnect()
        except socket.timeout:
            logger.debug("socket timeout from recvMsg %s", sys.exc_info())
            buf = b""
        else:
            pass

        return buf

    def recvAllMsg(self):
        cont = True
        allbuf = b""

        while cont and self.socket is not None:
            buf = self.socket.recv(4096)
            allbuf += buf
            logger.debug("len %d raw:%s|", len(buf), buf)

            if len(buf) < 4096:
                cont = False

        return allbuf

Respuesta1

4096 es el tamaño del búfer, no el número de puerto. Este error ocurre porque se sale de un hilo mientras otro intenta escribir (en una ubicación inexistente). Es un problema del IB, pero no debería causar ningún problema, simplemente es feo.

Respuesta2

Una solución alternativa para implementar en suClase EClient/EWrapper:

  1. Crear una función de apagado de socket
  2. Úselo antes de llamar al método de desconexión.
# create function
def _socketShutdown(self):
    self.conn.lock.acquire()
    try:
        if self.conn.socket is not None:
            self.conn.socket.shutdown(socket.SHUT_WR)
    finally:
        self.conn.lock.release()

# use it
self._socketShutdown()
time.sleep(1) 
self.disconnect()

información relacionada