博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈tcp粘包问题
阅读量:5050 次
发布时间:2019-06-12

本文共 3851 字,大约阅读时间需要 12 分钟。

第一部分:简介tcp socket通信的底层原理

原理解析图:

 

1 socket通信过程如图所示:首先客户端将发送内容通过send()方法将内容发送到客户端计算机的内核区,然后由操作系统将内容通过底层路径发送到服务器端的内核区,然后由服务器程序通过recv()方法从服务器端计算机内核区取出数据。 2 因此我们可以了解到,send方法并不是直接将内容发送到服务器端,recv方法也并不是直接将从客户端发来的内容接收到服务器程序内存中,而是操作自己机器的内核区。

 

第二部分:产生粘包的原因(只针对tcp)

产生粘包的情况有两种:

1 1:当连续发送数据时,由于tcp协议的nagle算法,会将较小的内容拼接成大的内容,一次性发送到服务器端,因此造成粘包2 3 2:当发送内容较大时,由于服务器端的recv(buffer_size)方法中的buffer_size较小,不能一次性完全接收全部内容,因此在下一次请求到达时,接收的内容依然是上一次没有完全接收完的内容,因此造成粘包现象。

也就是说:接收方不知道该接收多大的数据才算接收完毕,造成粘包。

 

第三部分:如何解决上述两种粘包现象?

思路一:对于第一种粘包产生方式可以在两次send()直接使用recv()来阻止连续发送的情况发生。代码就不用展示了。

思路二:由于产生粘包的原因是接收方的无边界接收,因此发送端可以在发送数据之前向接收端告知发送内容的大小即可。代码示例如下:

  方式一:分两次通讯分别传递内容大小和内容

  服务器端代码:

1 # __author__:Kelvin 2 # date:2019/4/28 21:36 3 from socket import * 4 import subprocess 5  6 server = socket(AF_INET, SOCK_STREAM) 7 server.bind(("127.0.0.1", 8000)) 8 server.listen(5) 9 10 while True:11     conn, addr = server.accept()12     print("创建了一个新的连接!")13     while True:14         try:15             data = conn.recv(1024)16             if not data: break17             res = subprocess.Popen(data.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,18                                    stderr=subprocess.PIPE)19             err = res.stderr.read()20             if err:21                 cmd_msg = err22             else:23                 cmd_msg = res.stdout.read()24             if not cmd_msg: cmd_msg = "action success!".encode("gbk")25             length = len(cmd_msg)26             conn.send(str(length).encode("utf-8"))27             conn.recv(1024)28             conn.send(cmd_msg)29         except Exception as e:30             print(e)31             break

  客户端代码:

1 # __author__:Kelvin 2 # date:2019/4/28 21:36 3 from socket import * 4  5 client = socket(AF_INET, SOCK_STREAM) 6 client.connect(("127.0.0.1", 8000)) 7 while True: 8     inp = input(">>:") 9     if not inp: continue10     if inp == "quit": break11     client.send(inp.encode("utf-8"))12     length = int(client.recv(1024).decode("utf-8"))13     client.send("ready!".encode("utf-8"))14     lengthed = 015     cmd_msg = b""16     while lengthed < length:17         cmd_msg += client.recv(1024)18         lengthed = len(cmd_msg)19     print(cmd_msg.decode("gbk"))

  方式二:一次通讯直接传递内容大小和内容

  服务器端:

1 # __author__:Kelvin 2 # date:2019/4/28 21:36 3 from socket import * 4 import subprocess 5 import struct 6  7 server = socket(AF_INET, SOCK_STREAM) 8 server.bind(("127.0.0.1", 8000)) 9 server.listen(5)10 11 while True:12     conn, addr = server.accept()13     print("创建了一个新的连接!")14     while True:15         try:16             data = conn.recv(1024)17             if not data: break18             res = subprocess.Popen(data.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,19                                    stderr=subprocess.PIPE)20             err = res.stderr.read()21             if err:22                 cmd_msg = err23             else:24                 cmd_msg = res.stdout.read()25             if not cmd_msg: cmd_msg = "action success!".encode("gbk")26             length = len(cmd_msg)27             conn.send(struct.pack("i", length))28             conn.send(cmd_msg)29         except Exception as e:30             print(e)31             break

  客户端:

1 # __author__:Kelvin 2 # date:2019/4/28 21:36 3 from socket import * 4 import struct 5  6 client = socket(AF_INET, SOCK_STREAM) 7 client.connect(("127.0.0.1", 8000)) 8 while True: 9     inp = input(">>:")10     if not inp: continue11     if inp == "quit": break12     client.send(inp.encode("utf-8"))13     length = struct.unpack("i",client.recv(4))[0]14     lengthed = 015     cmd_msg = b""16     while lengthed < length:17         cmd_msg += client.recv(1024)18         lengthed = len(cmd_msg)19     print(cmd_msg.decode("gbk"))

上述两种方式均可以解决粘包问题。

 

转载于:https://www.cnblogs.com/sun-10387834/p/10790999.html

你可能感兴趣的文章
JAVA 技术类分享(二)
查看>>
TensorFlow2.0矩阵与向量的加减乘
查看>>
NOIP 2010题解
查看>>
javascript中的each遍历
查看>>
String中各方法多数情况下返回新的String对象
查看>>
UVA11524构造系数数组+高斯消元解异或方程组
查看>>
爬虫基础
查看>>
jquery.lazyload延迟加载图片第一屏问题
查看>>
delphi.指针.PChar
查看>>
Objective - C基础: 第四天 - 10.SEL类型的基本认识
查看>>
android调试debug快捷键
查看>>
【读书笔记】《HTTP权威指南》:Web Hosting
查看>>
Inoodb 存储引擎
查看>>
数据结构之查找算法总结笔记
查看>>
Android TextView加上阴影效果
查看>>
Requests库的基本使用
查看>>
C#:System.Array简单使用
查看>>
「Foundation」集合
查看>>
二叉树的遍历 - 数据结构和算法46
查看>>
类模板 - C++快速入门45
查看>>