IB Python API-Socket WinError 10038

IB Python API-Socket WinError 10038

Dies ist in der API für Interactive Brokers als „connection.py“ codiert. Wenn es ausgeführt wird, gibt es den Fehler „Ein Vorgang wurde an etwas versucht, das kein Socket war“ zurück, bei „buf = self.socket.recv(4096)“. Ich habe versucht, den an recv übergebenen Wert auf 7497 zu ändern, damit er mit dem Socket-Port übereinstimmt, aber ich bekomme dieselbe Meldung. Ich denke, es könnte sich um einen Formatierungsfehler handeln, aber ich bin zu neu in Python, um das sicher zu wissen.

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

Antwort1

4096 ist die Puffergröße, nicht die Portnummer. Dieser Fehler tritt auf, weil ein Thread beendet wird, während ein anderer versucht zu schreiben (an einen nicht vorhandenen Ort). Es ist ein IB-Problem, sollte aber keine Probleme verursachen, es ist einfach nur hässlich.

Antwort2

Ein Workaround, den Sie bei IhremEClient / EWrapper-Klasse:

  1. Erstellen einer Socket-Shutdown-Funktion
  2. Verwenden Sie es, bevor Sie die Disconnect-Methode aufrufen
# 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()

verwandte Informationen