Python Socket API参考出处:http://blog.csdn.net/xiangpingli/article/details/47706707

使用socket.recv(pack_length)接收不定长的数据,如果数据包长度超过一定值,则接收的数据不全,同时还会多触发一次 socket.recv().

参照python3.4的文档可发现:

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.

上述的英文的大体意思为:从socket中接收数据。返回值是byts类型。接收的最大数量的byte为指定的bufsize.

root@iZ94nil6ddfZ:~# cat setsockopt_test.py
#!/usr/bin/python import socket SEND_BUF_SIZE = 4096 # 发送缓冲区的大小
RECV_BUF_SIZE = 4096 # 接收缓冲区的大小 def modify_buff_size():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
print "Buffer size [Before]: %d" %bufsize sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, SEND_BUF_SIZE)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, RECV_BUF_SIZE) bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
print( "Buffer size [After]: %d" %bufsize) if __name__ == '__main__':
modify_buff_size()

执行  

  bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)

得到电脑上的默认接收缓冲区的值为:8192

问题场景描述:

server端是erlang实现的,client端是Python3实现的,通讯协议为自定义的格式,每次交互的数据包都是不定长的数据包。

从server端取数据,因为没有指定查询条件,返回的数据的数据量在1000条左右,每一条的数据都包含多个的整数型和字符串型,byte大小为:26782。

如果取得的数据量比较多,每一次的请求数据,client 的socket.recv(packet_size)会执行多次。

解决方案:

            receiverBufsize = self._client_socket.getsockopt(
socket.SOL_SOCKET,
socket.SO_RCVBUF)
data_body = None
if receiverBufsize < pack_length: data_body = bytes()
left_pack_length = pack_length
while left_pack_length > 0: if left_pack_length > receiverBufsize:
body_part =self._client_socket.recv(receiverBufsize)
else:
body_part =self._client_socket.recv(left_pack_length)
data_body += body_part
left_pack_length -= receiverBufsize else:
data_body= self._client_socket.recv(pack_length)

个人注解:

Python的socket一次最多只能读出缓冲区的全部的数据,如果指定的数据包的大小大于缓冲区的大小,则读出的有效数据仅仅为缓冲区的数据。

如果能确定发送过来的数据大于缓冲区的大小,则需要多次:socket.recv(receiverBufsize),然后将收到的数据拼接成完整的数据包后再解析。

二次错误修正:

使用上边的解决方案,在收到较大的数据的时候,偶尔会出现 :

一个数据包读出来了,但是数据包的较靠后的一部分数据有问题,将数据包解析后发现只有前边的部分能正确解析、后边的部分解析出来全是无效的数据。同时还会多触发几次 socket.recv().

body_part =self._client_socket.recv(pack_length)
body_part_length = len(body_part) # body_part_length 、left_pack_length、以及上边提到的缓冲区的大小,这三个值都不一样大。

缓冲区,bufsize: 8192

下列的两个值是我电脑传输特定的数据包的时候的值:

pack_length :26782

body_part_length: 24460

热闹了,。。。。。函数api有问题

二次解决方案:

            had_received = 0
data_body = bytes()
while had_received < pack_length:
part_body= self._client_socket.recv(pack_length - had_received)
data_body += part_body
part_body_length = len(part_body)
#print('part_body_length', part_body_length)
had_received += part_body_length

手动点击测试 :至少在五分钟内的连续点击测试并没有出现第一次的解决方案的的部分数据无效的情况。

个人注解:

  未能确定出错的原因,个人猜测:对缓冲区的读数据尽量少次数的读吧。。。。。。

Python3的tcp socket接收不定长数据包接收到的数据不全。的更多相关文章

  1. Stm32使用串口空闲中断,基于队列来接收不定长、不定时数据

    串口持续地接收不定长.不定时的数据,把每一帧数据缓存下来且灵活地利用内存空间,下面提供一种方式供参考.原理是利用串口空闲中断和DMA,每当对方发来一帧完整的数据后,串口接收开始空闲,触发中断,在中断处 ...

  2. 关于socket客户端接收不定长数据的解决方案

    #!/usr/bin/env python3.5 # -*-coding:utf8-*- """ 本实例客户端用于不断接收不定长数据,存储到变量res "&qu ...

  3. STM32串口接收不定长数据原理与源程序(转)

    今天说一下STM32单片机的接收不定长度字节数据的方法.由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的A ...

  4. STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷

    STM32使用串口1配合DMA接收不定长数据,减轻CPU载荷 http://www.openedv.com/thread-63849-1-1.html 实现思路:采 用STM32F103的串口1,并配 ...

  5. STM32 HAL库使用中断实现串口接收不定长数据

    以前用DMA实现接收不定长数据,DMA的方法接收串口助手的数据,全部没问题,不过如果接收模块返回的数据,而这些数据如果包含回车换行的话就会停止接收,例如接收:AT\r\nOK\r\n,就只能接收到AT ...

  6. STM32之串口DMA接收不定长数据

    STM32之串口DMA接收不定长数据 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口 ...

  7. STM32 ~ USART接收不定长数据

    IDLE中断什么时候发生? IDLE就是串口收到一帧数据后,发生的中断.什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据. ...

  8. 串口配合DMA接收不定长数据(空闲中断+DMA接收)-(转载)

    1.空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断: 2.空闲中断是接收到一个数据以后,接收停顿超过一字节时间  认为桢收完,总线空闲中断是在检测到在接收数据后, ...

  9. 串口1配合DMA接收不定长数据(空闲中断+DMA接收)

    1.空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断: 2.空闲中断是接收到一个数据以后,接收停顿超过一字节时间  认为桢收完,总线空闲中断是在检测到在接收数据后, ...

随机推荐

  1. Spring自动装配Bean详解

    1.      Auto-Wiring ‘no’ 2.      Auto-Wiring ‘byName’ 3.      Auto-Wiring ‘byType 4.      Auto-Wirin ...

  2. C 指针使用误区

    /** *错误给指针赋常量 *知识点:指针存储内存地址 **/ #include <stdio.h>void main(){ //int *p_int = 123; //错误,不能直接给指 ...

  3. js动态创建表格,删除行列的小例子

    js动态创建表格,删除行列的实例代码. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  4. testbench常用语句 很详细相当实用

    内容 与可综合Verilog代码所不同的是,testbench Verilog是在计算机主机上的仿真器中执行的.testbench Verilog的许多构造与C语言相似,我们可在代码中包括复杂的语言结 ...

  5. linux系统信息查询及相关概念

    1.查看机器可以插几根内存条: /sbin/lspci  -v 或dmesg 或  dmidecode(需要root) 2.查看机器有几块盘,是否做raid: blkid 或 fdisk -l 或 s ...

  6. Qt入门-layout布局

    开发一个图形界面应用程序,界面的布局影响到界面的美观.在设计一个界面之前,应该考虑到开发的界面可能给不用的用户使用,而用户的屏幕大小.纵横比例.分辨率可能不同,界面还可能是可缩放的,程序应该可以适应这 ...

  7. singer页面点击歌手singer是跳转到singer-detail的设置

    1.创建components/singer-detail/singer-detail.vue 2.配置动态路由: { path: ':id', name:'singer-detail', compon ...

  8. Datax将本地文件导入Hbase数据库!!!酷酷酷

    Hbase Writer的json文件链接: https://github.com/alibaba/DataX/blob/master/hbase11xwriter/doc/hbase11xwrite ...

  9. 【Java】初始化过程

    以下程序执行的结果是: class X{ Y y=new Y(); public X(){ System.out.print("X"); } } class Y{ public Y ...

  10. vshare

    vshare 基于百度分享开发的支持VUE2.X的分享插件,为您带来更多的流量!提供多种风格按钮,代码加载更快,引入社会化流量,提升网页抓取速度等优点.github地址:https://github. ...