IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 面试经典:TCP粘包是怎么回事? -> 正文阅读

[网络协议]面试经典:TCP粘包是怎么回事?

前言

关于TCP协议的问题在面试中会经常被问道,尤其是在应届生面试中。

TCP协议是面向连接的可靠性协议。说它可靠并不表示数据信息一定会被对端接受,而是在传输失败后会放弃重传机制并中断连接来通知用户。它提供的只是数据可靠性的传输和故障通知。

回到TCP粘包这个问题上,TCP是数据流传输,数据流是只有起点和终点的字节数据序列,只有输入流和输出流。根本不存在“包”的概念。

那大家常说的粘包的“包”是指什么呢?

其实大家说的是应用层的包,应用层协议规定了包的结构和大小,本质上就是一段数据报文。

具体的包可能像这样

//简简单单 自定义应用层协议
struct Message {
    int packSize;
    int type;
    char buf[100];
};

//http 请求
GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

TCP粘包的原因

在说原因之前我先讲讲粘包的两种情况:

假设有A,B两个包,A包在B包之前

1.接收端接受缓冲区中有A包的一部分

2.接收端接受缓冲区中有A包和B包的一部分

上述情况都属于粘包。

发送端原因:

TCP连接在默认情况下开启Nagle算法优化。当一个连接上有待确认的数据时(也就是发送端没有收到接受端发回来的ACK),此时调用send发送数据,只是将数据填充到发送缓冲区中。等收到ACK后一起发送。

接收端原因:

处理数据不及时,数据都堆积在接收缓冲区中,致使AB两包相连。

如何解决粘包

1.固定包长度。每个包的大小都是一样的。
2.设置特定的结束标志。
3.在包中给定包大小。
例如:(固定前4个字节为包大小)
struct Message {
? ? int packSize;
? ? int type;
? ? char buf[100];
};

http协议就是使用了上述的2,3方法。http使用"\r\n"为结束标识。当为post请求时则有content-Length标识请求体长度。

关于Nagle算法

我再说说nagle算法吧,上面说得比较简略。

Nagle算法的目的是减少广域网中小分组的数目。也就是说尽可能在一次传输中多发送数据,从而减少频繁的网络交互。

/* 
* Return 0, if packet can be sent now without violation Nagle's rules:
* 1. It is full sized ? ???
* 2. Or it contains FIN. (already checked by caller)? ? ???
* 3. Or TCP_CORK is not set, and TCP_NODELAY is set. ? ? ???
* 4. Or TCP_CORK is not set, and all sent packets are ACKed. ? ? ???
*?With Minshall's modification: all sent small packets are ACKed.? 
*/???
static inline int tcp_nagle_check(const struct tcp_sock *tp,
                                        const struct sk_buff *skb,
                                     unsigned mss_now, int nonagle)
{
  return skb->len < mss_now &&((nonagle & TCP_NAGLE_CORK) ||
  (!nonagle && tp->packets_out && tcp_minshall_check(tp)));
} ? ?

根据linux源码可看出数据在哪些情况会立即发送:

1.当数据缓冲区数据>=MSS时。(MSS为TCP连接中最大报文长度,收发双方协商通信时每一个报文段所能承载的最大数据长度)

2.数据包包含FIN选项

3.TCP_CORK不设置,TCP_NODELAY选项设置

4.TCP_CORK不设置,收到接受方的ack确认


总结

TCP粘包就是应用层规定好了两个或多个数据包,同时存在于接受缓冲区,致使接收端要进行分包或组合的情况。

粘包情况是普遍存在的,通常通过指定包大小或指定结束标志来区分。

有些场景并不适合使用Nagle算法,像游戏类这种服务要求实时比较高的,就不需要开启。

可使用TCP选项,TCP_NODELAY关闭Nagle算法

最近和几个大学学弟聊天,他们在找实习面试时这种问题还是会经常被问到的,

这些都属于经典面试题,后续准备做一个面试系列,专门讲解一些应届生找工作或实习时遇到的真实面试问题。希望和大家一起进步。

?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-07 12:25:58  更:2021-08-07 12:26:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 23:19:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码