问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

TCP传输协议中如何解决丢包问题?

发布网友 发布时间:2022-04-24 08:06

我来回答

12个回答

懂视网 时间:2022-04-22 14:32

本文主要讲述的是怎么去解决tcp粘包问题,其一是分两次通讯分别传递内容大小和内容,其二是一次通讯直接传递内容大小和内容。想了解的朋友可以详细看看本篇文章,希望对你有所帮助。

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

原理解析图:

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

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

产生粘包的情况有两种:

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

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

相关教程:TCP/IP视频教程

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

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

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

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

  服务器端代码:

# __author__:Kelvin
# date:2019/4/28 21:36
from socket import *
import subprocess

server = socket(AF_INET, SOCK_STREAM)
server.bind(("127.0.0.1", 8000))
server.listen(5)

while True:
 conn, addr = server.accept()
 print("创建了一个新的连接!")
 while True:
 try:
  data = conn.recv(1024)
  if not data: break
  res = subprocess.Popen(data.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
     stderr=subprocess.PIPE)
  err = res.stderr.read()
  if err:
  cmd_msg = err
  else:
  cmd_msg = res.stdout.read()
  if not cmd_msg: cmd_msg = "action success!".encode("gbk")
  length = len(cmd_msg)
  conn.send(str(length).encode("utf-8"))
  conn.recv(1024)
  conn.send(cmd_msg)
 except Exception as e:
  print(e)
  break

 客户端代码:

# __author__:Kelvin
# date:2019/4/28 21:36
from socket import *

client = socket(AF_INET, SOCK_STREAM)
client.connect(("127.0.0.1", 8000))
while True:
 inp = input(">>:")
 if not inp: continue
 if inp == "quit": break
 client.send(inp.encode("utf-8"))
 length = int(client.recv(1024).decode("utf-8"))
 client.send("ready!".encode("utf-8"))
 lengthed = 0
 cmd_msg = b""
 while lengthed < length:
 cmd_msg += client.recv(1024)
 lengthed = len(cmd_msg)
 print(cmd_msg.decode("gbk"))

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

  服务器端:

# __author__:Kelvin
# date:2019/4/28 21:36
from socket import *
import subprocess
import struct

server = socket(AF_INET, SOCK_STREAM)
server.bind(("127.0.0.1", 8000))
server.listen(5)

while True:
 conn, addr = server.accept()
 print("创建了一个新的连接!")
 while True:
 try:
  data = conn.recv(1024)
  if not data: break
  res = subprocess.Popen(data.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
     stderr=subprocess.PIPE)
  err = res.stderr.read()
  if err:
  cmd_msg = err
  else:
  cmd_msg = res.stdout.read()
  if not cmd_msg: cmd_msg = "action success!".encode("gbk")
  length = len(cmd_msg)
  conn.send(struct.pack("i", length))
  conn.send(cmd_msg)
 except Exception as e:
  print(e)
  break

  客户端:

# __author__:Kelvin
# date:2019/4/28 21:36
from socket import *
import struct

client = socket(AF_INET, SOCK_STREAM)
client.connect(("127.0.0.1", 8000))
while True:
 inp = input(">>:")
 if not inp: continue
 if inp == "quit": break
 client.send(inp.encode("utf-8"))
 length = struct.unpack("i",client.recv(4))[0]
 lengthed = 0
 cmd_msg = b""
 while lengthed < length:
 cmd_msg += client.recv(1024)
 lengthed = len(cmd_msg)
 print(cmd_msg.decode("gbk"))

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

热心网友 时间:2022-04-22 11:40

一、回答这个问题之前,要考虑TCP协议为什么会丢包,在什么样的情况下会丢包。

1、TCP协议定义(Transimission Control Protocol)是以一种面向连接的、可靠的、基于字节流的传输层通信协议。

2、TCP是基于不可靠的网路实现可靠传输,肯定会存在丢包问题。

3、如果在通信过程中,发现缺少数据或者丢包,那边么最大的可能性是程序发送过程或者接受过程中出现问题。

例如:我有2台服务器 ,A和B服务器。

A服务器发送数据给B服务器频率过高时,B服务器来不及处理,造成数据丢包。(原因可能是程序逻辑问题,多线程同步问题,缓冲区溢出问题)

如果A服务器不对发送频率进行控制,或者数据进行重发的话,那么B服务器收到数据就会少。就会造成丢失数据

二、TCP协议丢包后,如何解决丢包的问题

为了满足TCP协议不丢包。TCP协议有如下规定

1、数据分片:发送端对数据进行分片,接受端要对数据进行重组,由TCP确定分片的大小并控制分片和重组

2、到达确认:接收端接收到分片数据时,根据分片数据序号向发送端发送一个确认

3、超时重发:发送方在发送分片时设置超时定时器,如果在定时器超时之后没有收到相应的确认,重发分片数据

4、滑动窗口:TCP连接的每一方的接受缓冲空间大小固定,接收端只允许另一端发送接收端缓冲区所能接纳的数据,TCP在滑动窗口的基础上提供流量控制,防止较快主机致使较慢主机的缓冲区溢出

5、失序处理:作为IP数据报来传输的TCP分片到达时可能会失序,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层;

6、重复处理:作为IP数据报来传输的TCP分片会发生重复,TCP的接收端必须丢弃重复的数据;

7、数据校验:TCP将保持它首部和数据的检验和,这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到分片的检验或有差错,TCP将丢弃这个分片,并不确认收到此报文段导致对端超时并重发

热心网友 时间:2022-04-22 12:58

TCP是一个“流”协议,一个详细的包将会被TCP拆分为好几个包上传,也是将会把小的封装成大的上传,这就是说TCP粘包和拆包难题。

热心网友 时间:2022-04-22 14:33

1.确认网络链路问题,ping测和traceroute确认链路是否健康。如果链路有问题,找对应网络管理员排查网络。
2.确认系统问题,通过wireshark或者tcpmp在应用系统两端抓包,定位问题所在,排查是发送或者接受系统网卡、性能问题
3.从tcp应用本身排查,通过在程序上添加调试代码,核查是否应用逻辑处理问题

热心网友 时间:2022-04-22 16:24

从tcp应用本身排查,通过在程序上添加调试代码,核查是否应用逻辑处理问题

热心网友 时间:2022-04-22 18:32

确认网络链路问题,确认系统问题,从tcp应用本身排查

热心网友 时间:2022-04-22 20:57

将一个大的拆成好几个小的传输

热心网友 时间:2022-04-22 23:38

看看网络是否卡顿,是否流畅

热心网友 时间:2022-04-23 02:36

可以通过代码调试,从而解决丢包

热心网友 时间:2022-04-23 05:51

这个你给加固它的传输通道。

热心网友 时间:2022-04-23 09:22

这个得看你的网络是否稳定

热心网友 时间:2022-04-23 13:10

确认网络链路问题,ping测和traceroute确认链路是否健康。如果链路有问题,找对应网络管理员排查网络
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
“苏大强”的本意是什么?抹黑江苏吗? 伦敦奥运会入场式各个国家和地区的先后顺序 参加奥运会入场式的前后顺序 神马是费用性斜视?没听说过,斜视不就是斗鸡眼么 小儿斜视原因 为了不出现重影,右眼会被推到外斜视眼位,称为“废用性斜视” 在八岁时玩鞭炮炸伤左眼,而形成左眼斜视,现在能治好吗 ...后左眼斜视外斜 左眼下半部有光感 视觉模糊 请问左手术的话 能恢复... 两眼视力差距大会怎么样 关于耳洞的小问题~有经验的和懂行的进~ 为什么网络会出现掉包? 上网老是丢包,请问是什么问题如何解决? 这个小区电信网络丢包率奇高怎么破 身份证丢了,可以在自助办证机进行补办吗? 咸宁身份证自助办理机器在哪 身份证自助办理需要多久取证? 成都身份证自助办理机哪里有 身份证自助办理机可以办理异地身份证吗? 哪里有身份证自助办理机? 要在自助机上办身份证需要什么手续? 补办身份证自助机需要什么,武汉哪些地方有? mysql 怎么修改表的comment 我想修改mysql数据库的名字,可以怎么修改 贵阳身份证自助办理机节假日可以办理吗? Mysql中怎么修改表中一个字段的类型 身份证自助办理机办理一般多久能拿到证? MySQL如何修改表格的字符集,如何修改某个字段的字符集 自助身份证办理机换新证需要提供户口本吗? 身份证自助办理机条件 mysql修改表结构和约束条件语句 ping路由器,延时很高还丢包,怎么解决? 青椒炒肉的配料有哪些? 青椒炒瘦肉有什么特点 青椒炒肉丝需要勾芡吗?它的正确做法是怎样的? 青椒炒瘦肉怎么炒好吃 青椒炒肉步骤: 青椒炒肉怎么做好吃 青椒炒瘦肉怎么炒才嫩 用什么油可以代替白边填充液? 手机的白边怎样永久的去除,用白边液怎么也是不管用,过几天就出来了? 手机上的白边填充剂怎么擦干净? 牛肉和胡萝卜能一起吃吗? 红萝卜炒牛肉可不可以一起吃 胡萝卜可以炒牛肉吃吗? 胡萝卜炒牛肉可以吃吗 牛肉可不可以和胡萝卜一起吃 胡萝卜和牛肉可以一起吃吗 牛肉胡萝卜可以一起吃吗 胡萝卜炒牛肉丝的禁忌 胡萝卜炒牛肉对身体有没有危害