python-day30--粘包

一、 什么是粘包

1.须知:只有TCP有粘包现象,UDP永远不会粘包

2.所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

二、两种情况下会发生粘包。

1.发送数据时间间隔很短,数据了很小,会合到一起,产生粘包

1 from socket import *
2 import time
3 phone=socket(AF_INET,SOCK_STREAM)
4 phone.connect((‘127.0.0.1‘,8080))
5
6 phone.send(‘helloworld‘.encode(‘utf-8‘))
7 phone.send(‘egon‘.encode(‘utf-8‘))

客户端

2.接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

from socket import *
import time
phone=socket(AF_INET,SOCK_STREAM)
phone.connect((‘127.0.0.1‘,8080))

phone.send(‘helloworld‘.encode(‘utf-8‘))
time.sleep(5)
phone.send(‘egon‘.encode(‘utf-8‘))

客户端

from socket import *
phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
phone.bind((‘127.0.0.1‘,8080))
phone.listen(5)
conn,client_addr=phone.accept()

data1=conn.recv(8)
print(‘data1: ‘,data1)
data2=conn.recv(20)
print(‘data2:‘,data2)
data3=conn.recv(20)
print(‘data3:‘,data3)
# 结果
# data1:  b‘hellowor‘
# data2: b‘ld‘
# data3: b‘egon‘

服务端

三、

拆包的发生情况

当发送端缓冲区的长度大于网卡的MTU时,tcp会将这次发送的数据拆成几个数据包发送出去。

补充问题一:为何tcp是可靠传输,udp是不可靠传输

基于tcp的数据传输请参考我的另一篇文章http://www.cnblogs.com/linhaifeng/articles/5937962.html,tcp在数据传输时,发送端先把数据发送到自己的缓存中,然后协议控制将缓存中的数据发往对端,对端返回一个ack=1,发送端则清理缓存中的数据,对端返回ack=0,则重新发送数据,所以tcp是可靠的

而udp发送数据,对端是不会返回确认信息的,因此不可靠

补充问题二:send(字节流)和recv(1024)及sendall

recv里指定的1024意思是从缓存里一次拿出1024个字节的数据

send的字节流是先放入己端缓存,然后由协议控制将缓存内容发往对端,如果待发送的字节流大小大于缓存剩余空间,那么数据丢失,用sendall就会循环调用send,数据不会丢失

四、解决粘包的low比处理方法

 1 import socket
 2 import subprocess
 3 import struct
 4 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
 5 phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加
 6 phone.bind((‘127.0.0.1‘,8082)) #绑定手机卡
 7 phone.listen(5) #开机
 8
 9 print(‘starting...‘)
10 while True: #链接循环
11     conn,client_addr=phone.accept() #等电话 (链接,客户的的ip和端口组成的元组)
12     print(‘-------->‘,conn,client_addr)
13     #收,发消息
14     while True:#通信循环
15         try:
16             cmd=conn.recv(1024)
17             if not cmd:break #针对linux
18             #执行cmd命令,拿到cmd的结果,结果应该是bytes类型
19             #。。。。
20             res = subprocess.Popen(cmd.decode(‘utf-8‘), shell=True,
21                                    stdout=subprocess.PIPE,
22                                    stderr=subprocess.PIPE)
23             stdout=res.stdout.read()
24             stderr=res.stderr.read()
25             #先发报头(转成固定长度的bytes类型)
26             header = struct.pack(‘i‘,len(stdout)+len(stderr))
27             conn.send(header)
28             #再发送命令的结果5
29             conn.send(stdout)
30             conn.send(stderr)
31         except Exception:
32             break
33     conn.close() #挂电话
34 phone.close() #关机

服务端

 1 import socket
 2 import struct
 3 phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机
 4 phone.connect((‘127.0.0.1‘,8082)) #绑定手机卡
 5 #发,收消息
 6 while True:
 7     cmd=input(‘>>: ‘).strip()
 8     if not cmd:continue
 9     phone.send(cmd.encode(‘utf-8‘))
10     #先收报头
11     header_struct=phone.recv(4)
12     unpack_res = struct.unpack(‘i‘, header_struct)
13     total_size=unpack_res[0]
14     #再收数据
15     recv_size=0 #10241=10240+1
16     total_data=b‘‘
17     while recv_size < total_size:
18         recv_data=phone.recv(1024)
19         recv_size+=len(recv_data)
20         total_data+=recv_data
21     print(total_data.decode(‘gbk‘))
22 phone.close()

客户端

时间: 2024-10-13 21:59:29

python-day30--粘包的相关文章

python的粘包和分包

twisted的Protocol.datareceived()能处理接收到的原始数据,既然是原始的,就可能和应用层定义的"包"有差异,即粘包和分包难以避免 看一段处理粘包的代码: #!/usr/bin/env python #coding=utf-8  import struct def mypack(data):     pack_format = '2I%ds'     return struct.pack(pack_format % len(data),100,len(data)

Python socket粘包问题

server端配置: import socket,subprocess,struct from socket import * server=socket(AF_INET,SOCK_STREAM) server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn,client_addr=server.accept() while True: try: cmd=conn.recv(1024) if len(cmd) == 0:bre

python 解决粘包现象(struct模块)

一. struct模块 该模块可以把一个类型,转换为固定长度的bytes import struct lst = [1,2,4,3,5,] lst1 = [1,2,4,3,5,7,8,9,] a = struct.pack('i',len(lst))#将列表的长度转化为固定的4字节 b = struct.pack('i',len(lst1)) print(a,len(a)) print(b,len(b)) 符号对应的类型以及转换之后的长度表 : struct模块实现大文件传输 : #server

python/socket编程之粘包

python/socket编程之粘包 粘包: 只有TCP有尿包现象,UDP永远不会粘包. 首先需要掌握一个socket收发消息的原理 发送端可以是1k,1k的发送数据而接受端的应用程序可以2k,2k的提取数据,当然也有可能是3k或者多k提取数据,也就是说,应用程序是不可见的,因此TCP协议是面来那个流的协议,这也是容易出现粘包的原因而UDP是面向笑死的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任一字节的数据,这一点和TCP是很同的.怎样定义消息呢?认为对方一次

Python网络编程03/ low版解决粘包问题

目录 Python网络编程03/ low版解决粘包问题 1.操作系统的缓存区 2.基于TCP协议的socket循环通信 2.1 服务端(server) 2.2客户端(client) 3.基于TCP协议的socket链接+循环 通信 3.1服务端(server) 3.2 客户端(client) 4.基于TCP协议的socket应用实例:执行远程命令 4.1服务端(server) 4.2客户端(client) 5.粘包现象 5.1服务端(server) 5.2客户端(client) 5.3展示收发问

Python网络编程04/recv原理/高大上版解决粘包方式

目录 Python网络编程04/recv原理/高大上版解决粘包方式 1.昨日内容回顾 2.recv工作原理 3.高大上版解决粘包方式(自定制报头) 3.1 解决思路: 3.2 服务端 3.3客户端 4.基于UDP协议的socket通信 4.1服务端 4.2客户端 Python网络编程04/recv原理/高大上版解决粘包方式 1.昨日内容回顾 1. 通信循环 2. 链接通信循环 3. 远程执行命令: subprocess.Popen() # bytes: 网络传输, 文件存储时. 4. 粘包现象

10.python网络编程(解决粘包问题 part 2)

一.什么时候会产生粘包现象. 只有在使用tcp协议的情况下才会产生粘包现象!udp协议永远不会! 发送端可以1k1k的把数据发送出去,接收端,可以2k2k的的去接收数据,一次可能会接收3k,也有可能1次接收6k. TCP协议是面向流的协议,这也是容易出现粘包问题的原因.而UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据,这一点和TCP是很不同的.怎样定义消息呢?可以认为对方一次性write/send的数据为一个消息,需要明白的是当对方

python学习_day30_基于tcp协议的粘包现象

1.基于远程执行命令的程序 需用到subprocess模块 服务端: #1.执行客户端发送的指令 import socket import subprocess phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.bind(('127.0.0.1',8090)) phone.listen(5) while True: conn,addr=phone.accept() print('IP:%s PORT:%s' %(addr[0

python开发socket网络编程基础:粘包问题&amp;udp套接字

一,发生粘包 服务器端 1 from socket import * 2 phone=socket(AF_INET,SOCK_STREAM) #套接字 3 phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #解决端口占用 4 phone.bind(('127.0.0.1',8080)) #绑定端口和Ip到套接字 5 phone.listen(5) 6 conn,client_addr=phone.accept() #等待tcp接受 7 8 9 # data1

python全栈开发基础【补充】解决tcp粘包

一.什么是粘包 须知:只有TCP有粘包现象,UDP永远不会粘包 粘包不一定会发生 如果发生了:1.可能是在客户端已经粘了 2.客户端没有粘,可能是在服务端粘了 首先需要掌握一个socket收发消息的原理 应用程序所看到的数据是一个整体,或说是一个流(stream),一条消息有多少字节对应用程序是不可见的,因此TCP协议是面向流的协议,这也是容易出现粘包问题的原因.(因为TCP是流式协议,不知道啥时候开始,啥时候结束).而UDP是面向消息的协议,每个UDP段都是一条消息,应用程序必须以消息为单位提