浅谈TCP和UDP
简介

在计算机网络中,TCP(传输控制协议)和UDP(用户数据报协议)是两个常用的传输层协议。它们分别提供了可靠的数据传输和快速的数据传送,成为互联网世界中的双子星。本文将探讨TCP和UDP的特点、优势和应用场景,以及如何选择合适的协议来满足不同的需求。
TCP定义
英文名:Transmission Control Protocol
中文名:传输控制协议
协议说明:TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。
举例:打电话,需要双方都接通,才能进行对话
特点:效率低,数据传输比较安全
UDP定义
英文名:User Datagram Protocol
中文名:数据报协议
协议说明:UDP是一种面向无连接的传输层通信协议。
举例:发短信,不需要双方建立连接,But,数据报的大小应限制在64k以内
特点:效率高,数据传输不安全,容易丢包
OSI模型与TCP/IP模型

TCP协议
TCP是一种面向连接的、可靠的传输控制协议,是互联网通信中最常用的协议之一。TCP的设计目标是提供可靠的数据传输、流量控制和拥塞控制机制,以确保数据在网络中准确无误地传输。

TCP协议总结起来主要有以下几个特点
面向连接:在TCP通信中,发送端和接收端之间需要建立一个可靠的连接,这个连接在数据传输结束后再关闭。连接的建立和断开是通过三次握手和四次挥手来完成的。
可靠性:TCP提供可靠的数据传输机制。它通过序列号、确认应答和重传机制来确保数据的准确传输。发送端将数据划分为称为TCP段的小块,并在每个段上添加一个序列号。接收端通过确认应答来确认已收到的数据,并可以要求发送端重新传输丢失的数据。
流量控制:TCP具有流量控制机制,用于控制数据发送的速率,以避免接收端无法处理过多的数据而导致的数据丢失。接收端可以通过窗口大小来通知发送端自己的接收能力,从而实现动态调整数据传输的速率。
拥塞控制:TCP通过拥塞控制机制来避免网络拥塞和数据丢失。它使用一种称为拥塞窗口的机制来控制数据发送的速率。当网络拥塞时,TCP会降低发送速率,从而减轻网络负载,保证网络的稳定性。
面向字节流:TCP是一种面向字节流的协议,将应用层传输的数据视为一连串的字节流。TCP会将数据划分为适当大小的数据段,并通过TCP头部中的序列号来对每个数据段进行标记,以便接收端正确地重组数据。
可靠性校验:TCP使用校验和机制来检测数据在传输过程中是否发生了错误。接收端会根据校验和的值判断数据是否被篡改,如果检测到错误,接收端会要求发送端重新传输数据。
有序性:TCP保证数据的有序传输。每个TCP段都有一个序列号,接收端根据序列号对接收到的数据进行排序,以确保数据按正确的顺序重新组装。
全双工通信:TCP支持全双工通信,即发送端和接收端可以同时进行发送和接收操作,实现双向的数据传输。
UDP协议

UDP是一种无连接的传输协议,相对于TCP而言,它具有以下特点:
- 无连接性:UDP是无连接的协议,发送端和接收端之间不需要建立和维护连接。每个UDP数据包都是独立的,包含完整的数据和目标端口信息。这使得UDP在数据传输的开销上比TCP更小。
- 快速传输:由于没有连接建立和维护的开销,UDP具有更低的延迟。数据包不需要等待确认应答或进行重传,因此可以更快地传输数据。这使得UDP适用于实时性要求高的应用场景,如音频和视频流传输、实时游戏和语音通信。
- 不可靠性:相对于TCP的可靠性传输,UDP是不可靠的。UDP数据包在发送后,不会保证到达接收端,也没有确认应答机制。如果在传输过程中出现丢包或错误,UDP协议本身不会进行重传或纠错,而是由应用层来处理数据的完整性和顺序性。
- 简单性:UDP的协议头较小,仅包含必要的信息,使得数据包的开销更小。UDP的设计相对简单,实现和处理也更加轻量化,使得它在资源有限的环境下更为适用。
- 支持广播和多播:UDP支持广播和多播功能。广播是将数据包发送到网络中的所有主机,而多播是将数据包发送到特定组的主机。这使得UDP适用于实现广播通信、流媒体传输和组播应用。
- 适应性:UDP对数据的处理方式非常灵活,没有严格的顺序要求。它适用于传输短消息、查询应答、简单请求响应等简单的通信模式。UDP也常用于DNS(域名系统)查询、SNMP(简单网络管理协议)以及一些轻量级的通信和传输协议。
TCP数据缓冲区
TCP协议是作用是用来进行端对端数据传送的,那么就会有发送端和接收端,在操作系统有两个空间即user space和kernal space。
每个Tcp socket连接在内核中都有一个发送缓冲区和接收缓冲区,TCP的全双工的工作模式以及TCP的流量(拥塞)控制便是依赖于这两个独立的buffer以及buffer的填充状态。
单工:只允许甲方向乙方传送信息,而乙方不能向甲方传送 ,如汽车单行道。
半双工:半双工就是指一个时间段内只有一个动作发生,甲方可以向乙方传送数据,乙方也可以向甲方传送数据,但不能同时进行,如一条窄马路同一时间只能允许一个车通行。
全双工:同时允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。
一个socket的两端,都会有send和recv两个方法,如client发送数据到server,那么就是客户端进程调用send发送数据,而send的作用是将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回。也就是说send()方法返回之时,数据不一定会发送到对端即服务器上去(和write写文件有点类似),send()仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中,发送是TCP的事情,和send其实没有太大关系。
接收缓冲区把数据缓存入内核,等待recv()读取,recv()所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面,并返回。若应用进程一直没有调用recv()进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。对于TCP,如果应用进程一直没有读取,接收缓冲区满了之后,发生的动作是:收端通知发端,接收窗口关闭(win=0)。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。
查看socket发送缓冲区大小,cat /proc/sys/net/ipv4/tcp_wmem
常见的问题
TCP粘包
TCP粘包问题是在TCP协议中常见的一个数据传输问题,指的是发送方连续发送的多个数据包在接收方接收时被粘在一起,导致接收方无法正确解析和处理数据包的边界。这种情况可能会对应用层造成困扰,因为接收方无法准确判断每个数据包的起始和结束位置,从而导致数据解析错误或数据丢失。

因为TCP是面向流,没有边界,而操作系统在发送TCP数据时,会通过缓冲区来进行优化,例如缓冲区为1024个字节大小。
- 如果一次请求发送的数据量比较小,没达到缓冲区大小,TCP则会将多个请求合并为同一个请求进行发送,这就形成了粘包问题。
- 如果一次请求发送的数据量比较大,超过了缓冲区大小,TCP就会将其拆分为多次发送,这就是拆包。
粘包常见解决办法
对于粘包和拆包问题,常见的解决方案有四种:
- 发送端将每个包都封装成固定的长度,比如100字节大小。如果不足100字节可通过补0或空等进行填充到指定长度;
- 发送端在每个包的末尾使用固定的分隔符,例如\r\n。如果发生拆包需等待多个包发送过来之后再找到其中的\r\n进行合并;例如,FTP协议;
- 将消息分为头部和消息体,头部中保存整个消息的长度,只有读取到足够长度的消息之后才算是读到了一个完整的消息;
- 通过自定义协议进行粘包和拆包的处理。
Netty对TCP粘包和拆包问题的处理
Netty对解决粘包和拆包的方案做了抽象,提供了一些解码器(Decoder)来解决粘包和拆包的问题。如:
LineBasedFrameDecoder:以行为单位进行数据包的解码;
DelimiterBasedFrameDecoder:以特殊的符号作为分隔来进行数据包的解码;
FixedLengthFrameDecoder:以固定长度进行数据包的解码;
LenghtFieldBasedFrameDecode:适用于消息头包含消息长度的协议(最常用);
基于Netty进行网络读写的程序,可以直接使用这些Decoder来完成数据包的解码。对于高并发、大流量的系统来说,每个数据包都不应该传输多余的数据(所以补齐的方式不可取),LenghtFieldBasedFrameDecode更适合这样的场景。
为什么UDP没有粘包?
UDP协议不会发生粘包问题的主要原因是UDP是面向数据报的协议,每个UDP数据包都是独立的、自包含的。在UDP中,每个数据包被视为一个独立的实体,没有像TCP那样的数据流概念,因此不会发生粘包现象。
UDP协议在传输数据时,每个数据包都有自己的报文头,其中包含了目标端口、源端口、数据长度等信息。在发送端,每个UDP数据包独立发送,并且每个数据包都有固定的大小。在接收端,每次接收到一个UDP数据包时,就会被视为一个完整的数据报,而不会与其他数据包发生合并或拆分的情况。
因此,UDP协议的特性决定了它不会发生粘包问题。每个UDP数据包都具有独立性和完整性,接收方可以准确地处理每个数据包,而不需要担心数据包的边界和顺序。
然而,尽管UDP不会发生粘包问题,但它也存在其他的问题,例如数据丢失、数据无序等。由于UDP是无连接、不可靠的协议,它不提供重传机制和确认应答机制,因此在网络不稳定或拥塞的情况下,UDP数据包可能会丢失或无序到达。因此,在使用UDP进行数据传输时,应用层需要自行处理这些问题,如使用序列号、确认应答等手段来确保数据的可靠性和顺序性。
什么是零拷贝?
即所谓的 Zero-copy, 就是在操作数据时, 不需要将数据 buffer 从一个内存区域拷贝到另一个内存区域. 因为少了一次内存的拷贝, 因此 CPU 的效率就得到的提升.
在 OS 层面上的 Zero-copy 通常指避免在 用户态(User-space) 与 内核态(Kernel-space) 之间来回拷贝数据. 例如 Linux 提供的 mmap 系统调用, 它可以将一段用户空间内存映射到内核空间, 当映射成功后, 用户对这段内存区域的修改可以直接反映到内核空间; 同样地, 内核空间对这段区域的修改也直接反映用户空间. 正因为有这样的映射关系, 我们就不需要在 用户态(User-space) 与 内核态(Kernel-space) 之间拷贝数据, 提高了数据传输的效率.
而需要注意的是, Netty 中的 Zero-copy 与上面我们所提到到 OS 层面上的 Zero-copy 不太一样, Netty的 Zero-coyp完全是在用户态(Java 层面)的, 它的 Zero-copy 的更多的是偏向于 优化数据操作 这样的概念.
Netty 的 Zero-copy 体现在如下几个个方面:
Netty 提供了 CompositeByteBuf 类, 它可以将多个 ByteBuf 合并为一个逻辑上的 ByteBuf, 避免了各个 ByteBuf 之间的拷贝.
通过 wrap 操作, 我们可以将 byte[] 数组、ByteBuf、ByteBuffer等包装成一个 Netty ByteBuf 对象, 进而避免了拷贝操作.
ByteBuf 支持 slice 操作, 因此可以将 ByteBuf 分解为多个共享同一个存储区域的 ByteBuf, 避免了内存的拷贝.
通过 FileRegion 包装的FileChannel.tranferTo 实现文件传输, 可以直接将文件缓冲区的数据发送到目标 Channel, 避免了传统通过循环 write 方式导致的内存拷贝问题.
Netty的接收和发送ByteBuffer使用直接DirectBuffer内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用JVM的堆内存进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于使用直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。
浅谈TCP和UDP的更多相关文章
- 浅谈tcp 与udp
tcp是一种面向连接的.可靠的.基于字节流的传输层通信协议.是专门为了在不可靠的互联网络上提供一个可靠的端到端字节流而设计的,面向字节流. udp(用户数据报协议)是iso参考模型中一种无连接的传输层 ...
- 浅谈TCP IP协议栈(三)路由器简介
读完这个系列的第一篇浅谈TCP/IP协议栈(一)入门知识和第二篇浅谈TCP/IP协议栈(二)IP地址,在第一篇中,可能我对协议栈中这个栈的解释有问题,栈在数据结构中是一种先进后出的常见结构,而在整个T ...
- Qt网络编程-书接上文,浅谈TCP文件收发,以及心跳包
qt网络编程-书接上文,浅谈文件收发 上文Qt网络编程-从0到多线程编程中谈到 在qt中的qtcpsocket通讯的用法,接下来浅谈一下关于tcp通讯的实际应用,当然了由于是浅谈,也不能保证其功能的完 ...
- 浅谈 TCP、IP、DNS 和 HTTP 的关系
一.浅谈三个协议的基本概念 1.IP 协议 按层次分,IP网际协议位于网络层,几乎所有的网络的系统都会用到 IP 协议,其重要性非同一般.IP 协议作用就是把各种数据包传送给对方,对方的地址就要看其 ...
- 浅谈TCP IP协议栈(四)IP协议解析
通过之前的网络层基础知识,IP地址以及路由器的简介,大家应该对于TCP/IP有一个大致的了解,在脑海里应该对于网络的几个基础概念有个大概的了解,简单点说整个协议栈就是在做一件事,规定网络报文(网络传输 ...
- 面试:浅谈tcp/udp
tcp是一种面向连接的.可靠的.基于字节流的传输层通信协议.是专门为了在不可靠的互联网络上提供一个可靠的端到端字节流而设计的,面向字节流. udp(用户数据报协议)是iso参考模型中一种无连接的传输层 ...
- 浅谈TCP/IP网络编程中socket的行为
我认为,想要熟练掌握Linux下的TCP/IP网络编程,至少有三个层面的知识需要熟悉: 1. TCP/IP协议(如连接的建立和终止.重传和确认.滑动窗口和拥塞控制等等) 2. Socket I/O系统 ...
- 测试那些事儿—浅谈TCP/IP协议
TCP/IP协议是一系列网络协议的总和,是构成网络通信的核心骨架. TCP/IP的工作原理通俗的讲就是一个主机的数据要经过哪些过程才能发送到对方的主机上. TCP/IP协议采用四层结构,分别为应用层, ...
- 浅谈TCP扫描与SYN扫描与FIN扫描
下面就这三种方法来小小的探讨一下,不对的地方还请多多指教! 1:TCP扫描 相对来说是速度比较慢的一种,为什么会慢呢?因为这种方法在扫描的时候会从本地主机的一个端口向目标主机的一个端口发出一个连接请求 ...
- 浅谈TCP优化
原文地址:http://kb.cnblogs.com/page/197406/ 很多人常常对TCP优化有一种雾里看花的感觉,实际上只要理解了TCP的运行方式就能掀开它的神秘面纱.Ilya Grigor ...
随机推荐
- [nefu]算法设计与分析-锐格实验
谈点个人感想:锐格这个题目和数据要是再不维护,估计直接就裂开了,跪求学校升级改进一下OJ系统和题目Orz 实验一 递归与分治 6104 #include<bits/stdc++.h> us ...
- 使用 SK 示例 探索 GitHub 存储库 中的机器人
微软 3月22日 一篇文章"Semantic-kernel 嵌入和记忆:使用聊天UI探索GitHub Repos"[1] ,文章中进行了展示了嵌入,该文章解释了他们如何帮助开发人员 ...
- 【原理揭秘】Vite 是怎么兼容老旧浏览器的?你以为仅仅依靠 Babel?
作者:京东科技 孙凯 一.前言 对前端开发者来说,Vite 应该不算陌生了,它是一款基于 nobundle 和 bundleless 思想诞生的前端开发与构建工具,官网对它的概括和期待只有一句话:&q ...
- Let's Encrypt 泛域名证书申请
泛域名 泛域名证书又名通配符证书是SSL证书中的其中一种形式,一般会以通配符的形式(如:*.domain.com)来指定证书所要保护的域名. OV证书和DV证书都会有通配符的域名形式提供,而EV证书一 ...
- 【Note】倍增
真的不会.QAQ 目录 简介 大家都见过的应用:倍增求 \(\text{LCA}\) 倍增求 \(\text{LCA}\) ,但是动态加点,但是不会 \(lct\) 例题:[ZJOI2012]灾难(D ...
- Exception-List
一.500错误:找不到 jar包 应用根目录/WEB-INF/lib目录中没有对应的jar包. ctrl+shift+alt+s,打开artifacts,发现outputRoot里缺少lib目录.添加 ...
- GPT-NER:通过大型语言模型的命名实体识别
讲在前面,chatgpt出来的时候就想过将其利用在信息抽取方面,后续也发现了不少基于这种大语言模型的信息抽取的论文,比如之前收集过的: https://github.com/cocacola-lab/ ...
- 【python爬虫】对站长网址中免费简历模板进行爬取
本篇仅在于交流学习 解析页面 可以采用xpath进行页面连接提取 进入页面 通过进入的页面可以得到下载地址 步骤: 提取表页面模板链接-->进入连接-->提取页面内下载地址连接--> ...
- 文心一言 VS chatgpt (12)-- 算法导论3.1 6~7题
六.证明:一个算法的运行时间为θ(g(n))当且仅当其最坏情况运行时间为O(g(n)),且其最好情况运行时间为Ω(g(n)) . 文心一言: chatgpt: 要证明「一个算法的运行时间为θ(g(n) ...
- golang在编程语言排行榜上排名第10,请不要说golang已死。
四月头条:编程语言 Zig 进入 TIOBE 指数前 50 名 最近,我们讨论了高性能编程语言的出现.由于需要处理的数据量越来越大,这些编程语言正在蓬勃发展.因此,C 和 C++ 在前十名中表现良好, ...