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. 深入mysql “ON DUPLICATE KEY UPDATE” 语法的分析

    本篇文章是对mysql “ON DUPLICATE KEY UPDATE”语法进行了详细的分析介绍,需要的朋友参考下. mysql “ON DUPLICATE KEY UPDATE” 语法 如果在IN ...

  2. 如何设置Docker容器中Java应用的内存限制

    如果使用官方的Java镜像,或者基于Java镜像构建的Docker镜像,都可以通过传递 JAVA_OPTS 环境变量来轻松地设置JVM的内存参数.比如,对于官方Tomcat 镜像,我们可以执行下面命令 ...

  3. android获取对话框文本注意事项

    1.View注意设置成final类型如final View layout=.. . 2.获取文本框对象时候格式EditText e = (EditText)layout.findViewById(R. ...

  4. python学习之base64模块

    常见方法: base64.encodebytes() 参数: 接收一个字节对象. 返回值: 返回base64编码的数据(以'\n'结尾的数据). base64.decodebytes() 参数: 接收 ...

  5. [转]手工实现RTTI

    运行时的动态类型检查(RTTI,Run Time Type Indentifiation)是c++中提供的一项语言机制,它主要用于判断多态对象的具体类型. 为什么不使用c++提供的RTTI功能  但c ...

  6. innerHTML属性,outerHTML属性,textContent属性,innerText属性区别详解

    innerHTML属性用来读取或设置某个节点内的HTML代码. outerHTML属性用来读取或设置HTML代码时,会把节点本身包括在内. textContent属性用来读取或设置节点包含的文本内容. ...

  7. 如何把高版本的sqlserver 还原到低版本的 sqlserver

    本例为sql2012 还原到sql2008. 要实现的功能是把sql2012的数据库备份到sql2008,数据库名字为Test,并且这两个数据库在不同的电脑中. 微软的软件设计方案基本上都是新版本兼容 ...

  8. LeetCode: Rotate List 解题报告

    Rotate List Given a list, rotate the list to the right by k places, where k is non-negative. For exa ...

  9. RTX——第9章 任务运行在特权级或非特权级模式

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章教程为大家讲解 RTX 运行模式的一个重要知识点,特权级模式和非特权级模式,有些资料或者书籍将非特权 ...

  10. JavaScript高级 面向对象(10)--onload与jq中ready的区别

    说明(2017.4.2): 1. 在body中放一个img标签,src链接一张图片,那么页面会先读取html的document文档,然后再读取外部资源(这里没加onload其实就是从上往下顺序读取). ...