def mp_worker(row):
ip = row[0]
ip_address = ip
tcp_port = 2112
buffer_size = 1024
# Read the reset message sent from the sign when a new connection is established
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print('Connecting to terminal: {0}'.format(ip_address))
s.connect((ip_address, tcp_port))
#Putting a breakpoint on this call in debug makes the script work
s.send(":08a8RV;")
#data = recv_timeout(s)
data = s.recv(buffer_size)
strip = data.split("$", 1)[-1].rstrip()
strip = strip[:-1]
print(strip)
termStat = [ip_address, strip]
terminals.append(termStat)
except Exception as exc:
print("Exception connecting to: " + ip_address)
print(exc)
上面的代码是导致问题的脚本部分。这是一个非常简单的函数,它根据数据库查询中传入的IP连接到套接字,并接收指示硬件固件版本的响应。
现在,问题是,当我在套接字上带有断点的调试中运行它时,我会从硬件中获得整个预期的响应,但是如果我那里没有断点,或者我已完全运行该脚本,仅用部分预期的消息响应。我尝试将两个time.sleep()放在发送之后,看它是否会获得整个响应,然后尝试在其中使用注释掉的recv_timeout()方法,该方法使用非阻塞套接字和超时来尝试获取一个整个响应,两者的结果完全相同。
请注意,这在脚本中起作用,所有内容都在一个主代码块中,但是我需要将此部分分成一个函数,以便可以在多处理库中使用它。我尝试在本地Windows 7计算机和Unix服务器上运行它,结果相同。
答案 0 :(得分:1)
我将扩大并重申我刚才发表评论的内容。我仍然不完全确定这两种情况下的不同行为背后是什么(除了时间猜测显然被试图包含sleep
所证实。
但是,这有点不重要,因为流套接字不能保证您一次获得所有请求的数据,也不能按请求分块获取。这由应用程序处理。如果在发送完整响应后服务器关闭了套接字,则可以替换:
data = s.recv(buffer_size)
使用recv()
直到收到零字节为止,这等效于从syscall中获取0
(EOF
):
data = ''
while True:
received = s.recv(buffer_size)
if len(received) == 0:
break
data += received
如果不是这种情况,则必须依靠您要一起考虑的固定或已知(开始时发送)的大小。或在协议级别进行处理(查找字符,用于发信号边界的序列。
答案 1 :(得分:0)
我最近在这里找到了一个解决方案,并以为可以将其发布,以防万一其他人遇到问题,我决定先尝试先调用socket.recv(),然后再调用socket.send(),然后再调用socket。之后再次调用recv(),似乎已经解决了该问题;我真的不能告诉你为什么它起作用。
data = s.recv(buffer_size)
s.send(":08a8RV;")
data = s.recv(buffer_size)