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. 模拟HTTP请求获取返回值

    package org.jeecgframework.core.util; import java.io.BufferedReader; import java.io.IOException; imp ...

  2. 查杀病毒的NB命令

    kill - `pgrep linux|awk '{++S[$1]}END{for (i in S) print i}'` teamkill #!/bin/bash set -x kill - `pg ...

  3. version `GLIBC_2.14' not found 解决方法.

    from http://blog.csdn.net/force_eagle/article/details/8684669 version `GLIBC_2.14' not found 解决方法. 一 ...

  4. Ajax实现异步刷新验证用户名是否已存在

    由于要做一个注册页面,看到许多网站上都是使用Ajax异步刷新验证用户名是否可用的,所以自己也动手做一个小实例 都是简单的实例,所以直接发代码 静态页面Ajax.html <html> &l ...

  5. python操作excel之 模块 xlrd

    xlrd是专门用来在python中读取微软execel的模块,可以自己直接下载安装,也可以通过包管理器安装. 官方资料: 下载地址:http://pypi.python.org/pypi/xlrd 官 ...

  6. C++笔记 2

    1.程序由函数组成,函数只完成自己特定的功能即可   把函数声明写在头文件里(想使用函数时,可直接导入头文件,调用函数),把函数实现写在".cc"文件中   把多个".c ...

  7. 怎样使GridView中满足某个条件的行可编辑,其余行不可编辑?

    DXperience是个很优秀的第三方控件包,使用起来非常方便,但有时候某些功能的实现在文档中不太容易找到解决方案,比如下面要提到的这个功能我就在文档中找了很久也没找到,最后还是在官方论坛上找到的. ...

  8. Clipboard获取内容C#

    一.获取文本  textBox1.Text = Clipboard.GetData("Text").ToString(); 二.获取图像             pictureBo ...

  9. PDNN: 深度学习的一个Python工具箱

    PDNN: 深度学习的一个Python工具箱 PDNN是一个在Theano环境下开发出来的一个Python深度学习工具箱.它由苗亚杰(Yajie Miao)原创.现在仍然在不断努力去丰富它的功能和扩展 ...

  10. git commit 多行注释方法说明

    为了提高项目质量,不仅仅是代码的质量,而且还包括代码管理的质量. 所以,详细的git commit message 必不可少. 现在记录一下git commit 多行详细的commit 信息. 首先, ...