Python socket 模块:Recv() 数据响应切断 [英] Python socket module: Recv() data response cut off

查看:101
本文介绍了Python socket 模块:Recv() 数据响应切断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试使用 Python 脚本控制智能配电盘.为了实现这一点,我使用了套接字模块的 TCP 连接.大约 75% 的时间,我得到了我正在寻找的响应/数据,并且一切正常.然而,大约 25% 的时间,响应被截断为完全相同的长度,1024 字节.这对我来说没有任何意义,因为我的缓冲区大小实际上设置为 2048 字节.我在使用 recv() 之间等待的速度似乎也不会影响/导致这种情况.尽管 TCP 是一个字节流,这是否仍然可能与数据包碎片有关?

I'm currently trying to control a smart power strip using a python script. To accomplish this, I'm using a TCP connection with the socket module. Around 75% of the time, I get the response/data I was looking for and everything works perfectly. However, around 25% of the time, the response is cut off at the exact same length, 1024 bytes. This doesn't make any sense to me, as my buffer size is actually set to 2048 bytes. The speed at which I wait in between using recv() doesn't seem to effect/cause this either. Altough TCP is a stream of bytes, is it still possible that this could have to do with packet fragmentation?

主代码

ip='192.168.0.62'
port=9999

sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_tcp.connect((ip, port))
sock_tcp.send(encrypt('{"system":{"get_sysinfo":{}}}'))
data = sock_tcp.recv(2048)
sock_tcp.close()
print len(data) #On succesful runs output is 1221, on unsuccesful runs it is 1024
rec = decrypt(data[4:])
print str(rec) #See output below

加密功能

def encrypt(string):
    key = 171
    result = pack('>I', len(string))
    for i in string:
        a = key ^ ord(i)
        key = a
        result += chr(a)
    return result

解密函数

def decrypt(string):
    key = 171
    result = ""
    for i in string:
        a = key ^ ord(i)
        key = ord(i)
        result += chr(a)
    return result

输出

我收到的字符串本身.它很可能不相关,但我想无论如何我都会包括它.这是变量rec的值.

Output

The string itself that I recieve. It's most likeley not relevant, but I thought I would include it anyway. This is value of the variable rec.

期望的和常规的输出

完整的所需输出

{"system":{"get_sysinfo":{"sw_ver":"1.0.6 Build 180627Rel.081000" , hw_ver": 1.0", 模式": HS300(美国)", 设备ID": 80067B24A755F99C4D6C1807455E09F91AB7B2AA", OEMID": 5C9E6254BEBAED63B2B6102966D24C17", HWID": 34C41AA028022D0CCEA5E678E8547C54",RSSI":-60,"longitude_i":-1222955,"latitude_i":379078,"alias":"TP-LINK_PowerStrip_4F01","mic_type":"IOT.SMARTPLUGSWITCH","feature":"TIM:ENE","mac":"B0:BE:76:12:4F:01","updating":0,"led_off":0,"children":[{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA00","state":0,"alias":"CezHeat","on_time":0,"next_action":{}type":-1},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA01","state":1,"alias":"CezUVB","on_time":191208,"next_action":{"type":"id"},80067B24A755F99C4D6C1807455E09F91AB7B2AA02","state":1,"alias":"CyanHeat","on_time":191208,"next_action":{"type":-1}},{"id","state":1"alias":"CyanHeat","next_action":{"type":-1}},{"id","67B2A59A59A59A59A59A50A30F"801,"alias":"ZanderHeat","on_time":191208,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA04","alias":1"CairoHeat","on_time":191208,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA05","state":1,"alias":","KodaMister191208,"next_action":{"type":-1}}],"child_num":6,"err_code":0}}}

{"system":{"get_sysinfo":{"sw_ver":"1.0.6 Build 180627 Rel.081000","hw_ver":"1.0","model":"HS300(US)","deviceId":"80067B24A755F99C4D6C1807455E09F91AB7B2AA","oemId":"5C9E6254BEBAED63B2B6102966D24C17","hwId":"34C41AA028022D0CCEA5E678E8547C54","rssi":-60,"longitude_i":-1222955,"latitude_i":379078,"alias":"TP-LINK_Power Strip_4F01","mic_type":"IOT.SMARTPLUGSWITCH","feature":"TIM:ENE","mac":"B0:BE:76:12:4F:01","updating":0,"led_off":0,"children":[{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA00","state":0,"alias":"CezHeat","on_time":0,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA01","state":1,"alias":"CezUVB","on_time":191208,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA02","state":1,"alias":"CyanHeat","on_time":191208,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA03","state":1,"alias":"ZanderHeat","on_time":191208,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA04","state":1,"alias":"CairoHeat","on_time":191208,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA05","state":1,"alias":"KodaMister","on_time":191208,"next_action":{"type":-1}}],"child_num":6,"err_code":0}}}

异常和罕见的输出

切断输出

{"system":{"get_sysinfo":{"sw_ver":"1.0.6 Build 180627Rel.081000" , hw_ver": 1.0", 模式": HS300(美国)", 设备ID": 80067B24A755F99C4D6C1807455E09F91AB7B2AA", OEMID": 5C9E6254BEBAED63B2B6102966D24C17", HWID": 34C41AA028022D0CCEA5E678E8547C54",RSSI":-59,"longitude_i":-1222955,"latitude_i":379078,"alias":"TP-LINK_PowerStrip_4F01","mic_type":"IOT.SMARTPLUGSWITCH","feature":"TIM:ENE","mac":"B0:BE:76:12:4F:01","updating":0,"led_off":0,"children":[{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA00","state":0,"alias":"CezHeat","on_time":0,"next_action":{}type":-1},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA01","state":1,"alias":"CezUVB","on_time":191207,"next_action":{"type":"id"},80067B24A755F99C4D6C1807455E09F91AB7B2AA02","state":1,"alias":"CyanHeat","on_time":191207,"next_action":{"type":-1}},{"id","state":1"alias":"CyanHeat","next_action":{"type":-1}},{"id","67B2A59A59A59A59A59A59A59A30A10001,"alias":"ZanderHeat","on_time":191207,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA04","alias":1"CairoHeat","on

{"system":{"get_sysinfo":{"sw_ver":"1.0.6 Build 180627 Rel.081000","hw_ver":"1.0","model":"HS300(US)","deviceId":"80067B24A755F99C4D6C1807455E09F91AB7B2AA","oemId":"5C9E6254BEBAED63B2B6102966D24C17","hwId":"34C41AA028022D0CCEA5E678E8547C54","rssi":-59,"longitude_i":-1222955,"latitude_i":379078,"alias":"TP-LINK_Power Strip_4F01","mic_type":"IOT.SMARTPLUGSWITCH","feature":"TIM:ENE","mac":"B0:BE:76:12:4F:01","updating":0,"led_off":0,"children":[{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA00","state":0,"alias":"CezHeat","on_time":0,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA01","state":1,"alias":"CezUVB","on_time":191207,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA02","state":1,"alias":"CyanHeat","on_time":191207,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA03","state":1,"alias":"ZanderHeat","on_time":191207,"next_action":{"type":-1}},{"id":"80067B24A755F99C4D6C1807455E09F91AB7B2AA04","state":1,"alias":"CairoHeat","on

结论

如果有人可以向我提供有关为什么输出/流被切断的解决方案或解释,我将不胜感激.我使用了很多来自这个开源模块的代码.我也想更多地了解这一切是如何运作的,所以如果你能解释得更多一点,我将不胜感激.

Conclusion

If anyone could provide me with a solution or explanation as to why the output/stream gets cut off, it would be much appreciated. I used a lot of the code from this open source module. I'm also looking to understand more of how this all works, so if you could explain a bit more I would really appreciate it.

推荐答案

根据 文档,bufsize 参数仅指定要读取的最大数据量:

As per the documentation, the bufsize argument only specifies the maximum amount of data to be read:

socket.recv(bufsize[, 标志])从套接字接收数据.回报value 是一个字节对象,表示接收到的数据.最大一次接收的数据量由 bufsize 指定.见Unix 手册页 recv(2) 了解可选参数的含义旗帜;默认为零.

socket.recv(bufsize[, flags]) Receive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.

为了确保完整的数据传输,可以使用这样的函数,它等待套接字连接的结束(由 recv 返回的空字符串表示):

To ensure full data transfer a function like this can be used, which waits for the end of the socket connection (indicated by and empty string returned from recv):

def recv_all(connection):
    """
    Function for all data

    :param connection: socket connection
    :return: received data
    """
    data = list()
    while True:
        data.append(connection.recv(2048))
        if not data[-1]:
            return b''.join(data)

另一个可能更适合您的应用程序的示例可能是等待固定的消息大小(如您的问题所示为 1221):

Another example that might fit your application better could be to wait for a fixed message size (1221 as indicated by your question):

def recv_message(connection):
    data = list()
    transferred_bytes= 0
    while transferred_bytes < 1221:
        data.append(connection.recv(min(1221-transferred_bytes, 2048)))
        if not data[-1]:
            raise RuntimeError("socket connection broken")
        transferred_bytes += len(data[-1])
    return b''.join(data)

这篇关于Python socket 模块:Recv() 数据响应切断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆