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:
- Crear una función de apagado de socket
- Ú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()