IB python api ソケット WinError 10038

IB python api ソケット WinError 10038

これは、Interactive Brokers の API で 'connection.py' としてコード化されています。実行すると、'buf = self.socket.recv(4096)' で 'ソケットではないものに対して操作が試行されました' というエラーが返されます。ソケット ポートと一致するように、recv に渡される値を 7497 に変更してみましたが、同じメッセージが表示されます。フォーマット エラーの可能性がありますが、Python は初心者なので、確実にはわかりません。

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

答え1

4096 はバッファ サイズであり、ポート番号ではありません。このエラーは、1 つのスレッドが終了したときに別のスレッドが (存在しない場所に) 書き込みを試みているために発生します。これは IB の問題ですが、問題を引き起こすことはありません。単に見苦しいだけです。

答え2

実装するための回避策EClient / EWrapper クラス:

  1. ソケットシャットダウン関数を作成する
  2. 切断メソッドを呼び出す前に使用してください
# 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()

関連情報