繁体   English   中英

套接字随机断开连接

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM