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은 포트 번호가 아닌 버퍼 크기입니다. 이 오류는 다른 스레드가 (존재하지 않는 위치에) 쓰기를 시도하는 동안 한 스레드가 종료되었기 때문에 발생합니다. 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()

관련 정보