Python3的tcp socket接收不定长数据包接收到的数据不全。

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

使用socket.recv(pack_length)接收不定长的数据,如果数据包长度超过一定值,则接收的数据不全。

参照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为缓冲区大小。

[email protected]:~# 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端非Python实现的,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),然后将收到的数据拼接成完整的数据包后再解析。

时间: 2024-10-07 11:26:13

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

TCP协议下Socket接收比较慢点原因

在做一个游戏,发现阻塞和异步方式接受服务端的包都很反应很慢(不是网速问题),本机访问本机没这个问题,局域网有感觉200ms左右的延迟,部分机型感觉明显,部分不明显.找了很多资料,查到下面的文章,总算明白了. https://support.microsoft.com/zh-cn/kb/214397 设计问题-通过使用 Winsock TCP 发送较小的数据段  电子邮件  打印 重要说明:本文是由 Microsoft 机器翻译软件进行的翻译并可能由 Microsoft 社区通过社区翻译机构(

STM32F4 UART1 DMA发送和接收不定长度数据

STM32F4 串口收发使用DMA还是很方便的.但是配置DMA时需要配置数据长度,这一点对于发送来说可以预估计自己发送的长度来配置DMA发送数据长度,但是对于接收不是很好解决,因为如果使用DMA接收中断是要配置的数据长度减到0才能出发中断.但是我们无法判断接受数据的长度,导致无法判断数据接收完成.网上有提出的解决方法是用定时器固定周期的读DMA接收的长度来判断是否接收完成,也有使用UART的空闲中断来处理的.在这里我使用UART的空闲中断来处理接收不定长数据.当然也要打开DMA接收完成中断,处理

USART与USB接收不定数据方法,标准库、HAL库都适用

很多时候,我们使用串口或USB接收数据时,往往不知道PC端会发多长的数据下来, 为了解决这个不定数据接收问题,在此各提供一个解决思路. 串口数据不定接收: 由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据, 由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机. IDLE就是串口收到一帧数据后,发生的中断.什么是一帧数据呢?比如说给单片机一 次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以 叫做一包数据. 还有一

TCP发送接收数据(一)

TCP发送接收数据 import java.io.IOException; import java.io.OutputStream; import java.net.Socket; /* * TCP协议发送数据: * A:创建发送端的Socket对象 *    这一步如果成功,就说明连接已经建立成功了. * B:获取输出流,写数据 * C:释放资源 * * 连接被拒绝.TCP协议一定要先看服务器. * java.net.ConnectException: Connectionrefused: c

TCP发送接收数据2

//客户端 package liu.net.tcp; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class Client3 { public static void main(String[] args) throws Unknown

USART DMA接送一帧数据(不定长)

内容来源于:http://blog.sina.com.cn/s/blog_777668c30102x4hz.html 1.DMA做所周知这个是好的东西,对于跑裸机的开发者来说是一个福音.但是很多工程师还是按照以前的方式来设计串口,本人看到了真的急的不行.多么好的东西就这样子暴遣天物!可能很多开发者会说DMA是定长的我收发的数据都是不定长的有什么用?如果听到这句话我保证该位同事没有好好研究过DMA.今天把自己DMA不定长发送接收程序贴上来.希望大家在开发的过程少受罪. 2.在大家要开始学习的过程中

【python】-- Socket接收大数据

Socket接收大数据 上一篇博客,就是说当服务器发送至客户端的数据,大于客户端设置的数据,则就会把数据服务端发过来的数据剩余数据存在IO缓冲区中,这样就会造成我们想要获取数据的完整性. 解决思路: 1.改大客户端接收的数据的大小,因为官方建议最多只能接收8k的数据,那服务端发送过来的数据很容易就会大于8K,这个思路并不能从根本上解决问题(不建议使用) 2.客户端可以多收几次,服务端给客户端发数据之前,先计算一下要发给客户端数据大小(len()判断文件长度) ,比如说要发给客户端数据是5k大小,

tcp socket

1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在"无差别"的网络之上.建立起一个TCP连接需要经过"三次握手":第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK

TCP连接建立的三次握手过程可以携带数据吗?

前几天实验室的群里扔出了这样一个问题:TCP连接建立的三次握手过程可以携带数据吗?突然发现自己还真不清楚这个问题,平日里用tcpdump或者Wireshark抓包时,从来没留意过第三次握手的ACK包有没有数据.于是赶紧用nc配合tcpdump抓了几次包想检验一下.但是经过了多次实验,确实都发现第三次握手的包没有其它数据(后文解释).后来的探究中发现这个过程有问题,遂整理探究过程和结论汇成本文,以供后来者参考. 先来张三次握手的图(下面这张图来自网络,若侵犯了作者权利,请联系我删除): RFC79