[英]Socket loses connection randomly
我有套接字将Prologixx GPIB查询为ETH0。 我得到了朋友执行此操作的代码。 在Win 10中,套接字随机获得超时,有时计算机似乎关闭了连接。 我想认识到,套接字有问题,无法重新启动它。
有两条消息:
_recv [WinError 10035]无法立即完成非阻塞套接字操作
这只会产生无效的结果,我会检查结果是否合理。 也只是暂时的
_send [WinError 10053]建立的连接被主机中的软件中止了
这是永久的。 该程序像以前一样运行,只是死了没有得到新的结果。 测试新结果很困难,因为它们是温度,而且我会稳定一段时间。
import socket
from numpy import nan
from time import sleep
class PrologixGPIBEthernet:
PORT = 1234
def __init__(self, host, timeout=1):
self.host = host
self.timeout = timeout
self.socket = socket.socket(socket.AF_INET,
socket.SOCK_STREAM,
socket.IPPROTO_TCP)
self.socket.settimeout(self.timeout)
def connect(self):
self.socket.connect((self.host, self.PORT))
self._setup()
def close(self):
self.socket.close()
def select(self, addr):
self._send('++addr %i' % int(addr))
def write(self, cmd):
self._send(cmd)
def read(self, num_bytes=1024):
self._send('++read eoi')
return self._recv(num_bytes)
def query(self, cmd, buffer_size=1024*1024):
self.write(cmd)
return self.read(buffer_size)
def _send(self, value):
encoded_value = ('%s\n' % value).encode('ascii')
try:
s = self.socket.send(encoded_value)
except Exception as e:
print('_send', e)
def _recv(self, byte_num):
try:
value = self.socket.recv(byte_num).decode('ascii')
except Exception as e:
print (',_recv', e)
value = 'ERROR'
return value
def _setup(self):
# set device to CONTROLLER mode
self._send('++mode 1')
# disable read after write
self._send('++auto 1')
# set GPIB timeout
# self._send('++read_tmo_ms %i' % int(self.timeout*1e3))
# do not require CR or LF appended to GPIB data
# self._send('++eos 3')
我不确定错误消息,但这听起来与我的经验相似。
我将prologix设备称为“解释器”,因为它无法与SCPI无缝配合使用。
例如,对于普通的SCPI仪器,我可以要求设备执行测量,然后可以要求读取该测量,完成后它会给我响应。 只要超时时间长,它就会挂起,直到缓冲区被填满,然后返回结果。 (注意:这不是您应该采取的方式。使用轮询或中断是实现设备查询的好方法。)
Prologix设备可能会与时间混淆。 如果我尝试通过发送读取测量值的命令来复制SCPI的工作方式(如上所述),但是这次需要5秒钟来进行该测量并将其放入缓冲区。 在5秒钟过去之前,我问prologix结果是什么,它将尝试查找结果,但是缓冲区为空,因此没有任何返回值。 5秒钟后,缓冲区已满,但prologix不知道这一点,并停留在此状态。 这是您获得套接字超时的地方。
解决此问题的正确方法是使用prologix中的轮询功能在缓冲区有结果时进行计算。 但这不是我要做的事情。
技巧1)确保有足够大的延迟,但是您并不总是知道需要多长时间,并且会增加脚本延迟。
哈克2)故意强迫您的脚本超时并重试。 这就是我已经实现的。 我知道这很丑陋,但是当我尝试找出问题所在时,它很快就起作用了。
def read_timeout_poll(self, repeat):
# start_time = time.time() # Used if you want to see how long it takes
mesg = ""
for _ in range(repeat):
try:
sendData = "++read\n"
self.prolSock.send(sendData.encode())
mesg = self.prolSock.recv(self.BUFSIZ)
break
except socket.timeout:
time.sleep(1)
except socket.error as e:
return "Python Error sending data: " + str(e)
break
# print(f"read poll operation took {:.0f} seconds".format(time.time() - start_time)) # This is a guide to see how long it takes to get a result in the buffer
return mesg
尊敬的Zircatron谢谢您的回答和建议。 随机发生的超时并没有那么大的问题,正如您所建议的,请稍后再试。 当(prologixx?)断开连接时,可能会出现问题。 最后,当发生多次超时而无法正常运行时,我将不得不重新建立连接。 更加丑陋,但我的构想已经用光了……
愚蠢的是,我们没有足够的声誉,因此无法在stackoverflow中评论彼此的响应。
我觉得我只了解问题的一半。 为了帮助您,发生错误的顺序是什么?发生错误时您要尝试发送什么? 您能否给出导致错误的代码示例?
您的代码注释显示为“#禁用写后读取”,但是,您已启用“ self._send('++ auto 1')”。 我会禁用它。 我发现启用它并不能完全控制命令序列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.