尝试使用Python从网络设备上的TCP套接字连接获取数据

尝试使用Python从网络设备上的TCP套接字连接获取数据,python,sockets,tcp,Python,Sockets,Tcp,我正在尝试编写一个简单的Python脚本,该脚本连接到许多Fluke温湿度计(DewK 1620A),并将温度和湿度读数写入一个文件,然后将其输入Splunk。这是我第一次尝试使用Python,我非常接近,但似乎无法确定如何通过TCP套接字获取数据 概述 脚本从外部JSON读取设备列表,然后打开到每个设备的连接,发送命令获取当前读数,然后将这些读数写入文件 在我的第一次迭代中,我只进行了一次“data=s.recv(64)”调用,但设备在返回完整结果时不一致。有时我会得到完整的结果(即“69.6

我正在尝试编写一个简单的Python脚本,该脚本连接到许多Fluke温湿度计(DewK 1620A),并将温度和湿度读数写入一个文件,然后将其输入Splunk。这是我第一次尝试使用Python,我非常接近,但似乎无法确定如何通过TCP套接字获取数据

概述 脚本从外部JSON读取设备列表,然后打开到每个设备的连接,发送命令获取当前读数,然后将这些读数写入文件

在我的第一次迭代中,我只进行了一次“data=s.recv(64)”调用,但设备在返回完整结果时不一致。有时我会得到完整的结果(即“69.64,45.9,0,0”),而其他时候我只能得到部分读数(即“69.64,4”)

而真循环 在做了一些研究之后,我开始看到使用while-True循环在第二次(或第三次)传递中获取“其余”数据的建议。我用以下内容更改了我的简单s.recv呼叫:

while True:
     data = s.recv(64)           # Retrieve data from device
     if not data:                # If no data exists, break loop
          continue
     f.write(data.decode())      # Write data to logfile
不幸的是,现在脚本无法完成。我怀疑循环没有退出,但响应不应该超过24字节。我不知道如何测试和退出循环。我尝试添加一个超时,但这会破坏整个脚本

connectDeviceCp.py

import datetime
import json
import socket

# the command to be passed to the device
command = "read?\r"

# open the deviceLocation.json file for reading
jsonFile = open("devices.json", "r", encoding="utf-8")

# load the contents of the json file into 
locationFile = json.load(jsonFile)
jsonFile.close()

# for each device, connect & retrieve device readings
for device in locationFile["devices"]:

    location = device["location"]
    host = device["host"]
    portStr = device["port"]

    # convert the portStr variable from string to integer
    port = int(portStr)
    
    # open log file for appending.
    f = open("log/" + location + ".log", "a")

    try:

        # create a socket on client using TCP/IP
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        
        # set socket timeout to 3 seconds
        s.settimeout(10)
        
        # connect to host and port
        s.connect((host, port))

    except TimeoutError:

        # write to the log file if the host cannot be reached
        f.write(('\n{:%Y-%m-%d %H:%M:%S} - '.format(datetime.datetime.now())) + location + " - Error: " + host + ":" + portStr + " does not respond.")

    else:

        # send the command to the device
        s.sendall(command.encode())

        # write the timestamp and location to the log
        f.write(('{:%Y-%m-%d %H:%M:%S} - '.format(datetime.datetime.now())) + location + " - ")

        while True:
            data = s.recv(64)           # Retrieve data from device
            if not data:                # If no data exists, break loop
                break
            f.write(data.decode())      # Write data to logfile
        
        # --- The following work except the device doesn't always spit out all the data.
        # receive message string from device
        #data = s.recv(64)

        # write returned values to log file.
        #f.write(data.decode())

    finally:

        # disconnect the client
        s.close()      

        # close log file
        f.close()

设备通过以
\r
终止的线路进行面向线路的通信,因此只需读取整条线路-将while True循环替换为


如果没有数据:continue
应该是
如果没有数据:break
如果要离开循环<代码>继续只会导致跳过对
写入
的调用。最初它是“中断”的,然后我将其更改为在发布前对其进行尝试。它仍然不会退出。如果循环从未退出,则
如果不是数据
必须永远不会为真。仔细检查
数据
是什么(在里面放一张
打印文件)。这就是我困惑的地方。如果我与netcat连接,我可以发送命令并接收响应。没有数据流。当我更改打印输出时,我得到如下结果:b'76'和b'.84,38.4,70.11,49.3\r'在新行上,然后什么也没有。它只是挂在那里,好像在等待不来的数据。不来更多的数据是可以理解的,因为要实现这一点,必须向设备发送另一个读取命令。不幸的是,这也不起作用。它仍然挂起并且从不写入数据。在写入之前,我添加了一个
print(data)
调用,它不会显示任何返回的内容。我尝试显式地将makefile模式设置为read,并为readline设置字节,但这两种模式似乎都没有任何影响。啊,我刚刚在《用户指南》中读到:响应以回车符终止(串行接口可以配置为也发送新行字符)。这就解释了为什么
readline()
(等待NL)不起作用。我调整了答案。这似乎确实起到了作用。我已经运行了很多次了,结果和我预期的完全一样。我在《用户指南》中也看到了这一点,但除了将其放在命令中之外,我不知道如何使读取操作终止。非常感谢。
        data = s.makefile(newline='\r').readline()
        f.write(data)      # Write data to logfile