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