【Linux】UDP与TCP协议

目录

UDP协议

1.1通信流程

1.2函数 

socket

bind

 sendto

recvfrom

close 

1.3实现udp通信

TCP协议

1.1TCP头部结构

1.2通信流程

三次握手

正式通信

四次挥手

1.3协议特性

面向字节流

可靠传输

序列号和确认号

重传机制

流量控制和拥塞控制

1.4常用函数

socket

bind

listen

accept

connect

send

recv

close 

1.5实现tcp通信


socket又称套接字,他的存在是为了解决:

  1. 不同协议的识别TCP UDP
  2. 不同主机的识别(哪个IP发 哪个IP收)
  3. 不同进程的识别(哪个端口发 哪个端口收) 

UDP协议

        UDP(user datagram protocol)的中文叫用户数据协议报,属于传输层。UDP是面向非连接的协议,它不与对方建立连接,而是直接把我要发的数据报发给对方。所以UDP适用于一次传输数据量很少、对可靠性要求不高的或对实时性要求高的应用场景。

1.1通信流程

udp通信直接传输数据,不关心数据是否丢包不会进行重传。

1.2函数 

socket

#include <sys/socket.h>

int socket(int family,int type,int protocol);

  • 功能:创建一个用于网络通信的socket套接字
  • family:协议族(AF_INET(IPv4)、AF_INET6(IPv6)、PF_PACKET(链路层编程))
  • type:套接字类(SOCK_STREAM(流式套接字)、SOCK_DGRAM(数据报式套接字)SOCK_RAW(原始套接字))
  • protocol:协议类别(0、IPPROTO_TCP、IPPROTO_UDP)一般置0
  • 返回值:套接字

bind

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
  • 功能:将socket与本机上的一个端口绑定,随后就可以在该端口监听服务请求
  • sockfd:正在监听端口的套接口文件描述符,通过socket获得
  • addr:需要绑定的IP和端口
  • addrlen:addr的结构体的大小
  • 返回值:失败返回一个小于0的值,成功返回大于等于0的值

一般只有服务器端才需要“显示”绑定端口;client的端口号一般由client的OS随机选择,client不需要“显示”地绑定IP和端口号,当client第一次给服务器发消息时OS会自动绑定IP和端口号。

struct sockaddr
{sa_family_t sa_family; // 2字节char sa_data[14] //14字节
};
  • struct sockaddr_in:IPv4地址结构
  • struct sockaddr:通用地址结构
_sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);//填服务器端的信息
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons(_localport);
local.sin_addr.s_addr = INADDR_ANY;//将套接字与服务器端信息绑定
int n = ::bind(_sockfd, (struct sockaddr *)&local, sizeof(local));

 sendto

#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
              const struct sockaddr *dest_addr, socklen_t addrlen);
  • 功能:发送数据、
  • sockfd:正在监听端口的套接字文件描述符,通过socket获得。
  • buf:发送缓冲区,往往是使用者定义的数组,该数组装有要发送的数据
  • len:发送缓冲区的大小,单位是字节
  • flags:填0即可
  • dest_addr:指向接收数据的主机地址信息的结构体,也就是该参数指定数据要发送到哪个主机哪个进程
  • addrlen:表示第五个参数所指向内容的长度
  • 返回值:成功返回发送数据长度,失败返回-1。

recvfrom

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                struct sockaddr *src_addr, socklen_t *addrlen);

  • sockfd:正在监听端口的套接口文件描述符,通过socket获得
  • buf:接收缓冲区,往往是使用者定义的数组,该数组装有接收到的数据
  • len:接收缓冲区的大小,单位是字节
  • flags:一般置0
  • src_addr:指向发送数据的主机地址信息的结构体,也就是我们可以从该参数获取到数据是谁发出的
  • addrlen:表示第五个参数所指向内容的长度
  • 返回值:成功返回接收成功的数据长度,失败返回-1

close 

#include <unistd.h>
int close(int fd);

  • 功能:关闭某个文件描述符
  • fd:socket产生的fd(返回值)

1.3实现udp通信

udp通信的简单实现:Linux/udp_echo_server · swi/c++ - 码云 - 开源中国

TCP协议

        TCP是面向连接的协议,这是因为在一个应用进程可以开始向另一个应用进程发送数据之前,这两个进程必须先相互“握手”,即它们必须相互发送某些预备报文段,以建立确保数据传输的参数。它有以下几个特点:

  1. 面向连接:TCP一定是“一对一”的,无法像 UDP 协议那样在同一时刻像多个主机发送消息,即无法做到一对多;
  2. 可靠的:无论的网络链路中出现了怎样的链路变化,TCP 都可以保证一个报文一定能够到达接收端(当然不是说绝对可靠);
  3. 基于字节流:消息是“没有边界”的,所以无论我们消息有多大都可以进行传输。并且消息是“有序的”,当前一个消息没有收到的时候,即使它先收到了后面的字节已经收到,那么也不能扔给应用层去处理,同时对重复的报文会自动丢弃。

1.1TCP头部结构

 

  • 序列号:在连接建立时由计算机计算出的初始值,通过 SYN 包传给对端主机,每发送一次新的数据包,就累加一次该序列号的大小。用来解决网络包乱序问题
  • 确认应答号:指下次期望收到的数据的序列号,发送端收到这个确认应答以后可以确认确认应答号减一的数据包已经被正常接收。主要用来解决不丢包的问
  • ACK:用以指示确认字段中的值是有效的,即该报文段包括一个对已被成功接收的报文段的确认
  • RST:用以指示连接的强制拆除,当接收到错误连接时会发送RST位置为1的报文
  • SYN:用以指示连接的建立,该位为1的报文表示希望建立连接
  • FIN:用以指示连接的终止,该位为1的报文表示希望断开连接

1.2通信流程

三次握手

正式通信

 建立连接过程:

        服务端创建完监听套接字使用accept等待用户连接,当用户连接时监听套接字会起到"接客"的作用,此时再创建一个新的套接字来进行服务,而监听套接字继续等待新的用户。用于服务的套接字由accept函数返回。

四次挥手

        最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。

  • 第一次挥手 客户端发出连接释放报文,并且停止发送数据。此时客户端进入FIN-WAIT-1(终止等待1)状态。
  • 第二次挥手 服务器端接收到连接释放报文后,发出确认报文(应答)。此时服务端就进入了CLOSE-WAIT 关闭等待状态。
  • 第三次挥手 客户端接收到服务器端的确认请求后,客户端就会进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文,服务器将数据发送完毕后,就向客户端发送连接释放报文,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  • 第四次挥手 客户端收到服务器的连接释放报文后,发出应答此时,此时客户端就进入了TIME-WAIT(时间等待)状态,但此时TCP连接还未终止,必须要经过2MSL后(等待最长报文寿命时间,确保发送的应答被服务端收到),当客户端撤销相应的TCB后,客户端才会进入CLOSED关闭状态,服务器端接收到确认报文后,会立即进入CLOSED关闭状态,到这里TCP连接就断开了,四次挥手完成。

1.3协议特性

面向字节流

TCP以字节流的方式传输数据,没有消息边界,需要应用层进行数据的分包和组包12。这种方式使得TCP能够灵活地处理各种长度的数据,但也可能导致黏包问题。黏包问题可以通过以下方法解决:

  1. 数据定长:规定数据的长度。

  2. 特殊字符进行间隔:使用特殊字符分隔数据。

  3. 在不定长数据的应用层头部中添加数据长度字段:接收方根据头部长度,接收该长度的数据。

可靠传输

TCP提供可靠的数据传输服务,能够在数据传输过程中检测和纠正错误,确保数据的完整性、顺序性和可靠性。TCP通过以下机制确保数据的可靠传输:

  • 序列号和确认号:每个数据包都有一个序列号,接收方通过确认号告知发送方哪些数据已成功接收。

  • 重传机制:如果发送方未收到确认,会重新发送数据包。

  • 流量控制:通过滑动窗口机制,动态调整发送速率,避免接收方缓冲区溢出。

  • 拥塞控制:通过慢启动、拥塞避免等算法,动态调整发送速率,避免网络拥塞。

序列号和确认号

序列号(seq)

        序列号的主要作用是跟踪每个数据包中的数据在整个数据流中的位置。当TCP连接建立时,每一端都会随机选择一个初始序列号(ISN),之后传输的数据包的序列号将基于这个初始值递增。例如,如果一个数据包的序列号是100,且包含100字节的数据,那么下一个数据包的序列号将从200开始。这样,即使数据包在传输过程中到达顺序被打乱,接收端也能根据序列号重新组装数据,确保数据的顺序性和完整性。

确认号(ack)

        确认号则是接收端用来告诉发送端哪些数据已经被成功接收的。当接收端收到数据后,它会发送一个确认包,其中包含的确认号是接收到的数据的序列号加1。发送端通过检查这个确认号来确定数据是否需要重传。例如,如果发送端收到的确认号是101,那么它知道序列号为100的数据包已被接收端成功接收。

 应答的情况有以下两种:

 

重传机制

超时重传

        当TCP发送一个数据包后,它会启动一个定时器等待接收方的确认应答(ACK)。如果在定时器到期之前没有收到ACK,TCP会认为数据包可能已丢失,并重新发送该数据包。这个过程称为超时重传。超时重传时间(RTO)的设置非常重要,它应该略大于数据包往返时间(RTT)。

快速重传

        快速重传是另一种重传机制,它不依赖于定时器,而是基于接收到的重复ACK信号。如果发送方连续收到三个相同的ACK,它会立即重传那些被认为丢失的数据包,而不需要等待定时器超时。

超时重传:

(数据丢包)

(应答丢包) 

 为什么要等待一个特定时间?
        如果该等待时间过长会导致网络空隙时间增大,降低网络传输效率。如果等待时间过短,可能会在应答未到来时进行重传,导致网络负荷增大。

 快速重传:

流量控制和拥塞控制

流量控制:

作用:为了解决发送方和接收方发送和接收能力不匹配而导致的数据丢失问题,当发送方发送的太快,接收方来不及接受就会导致数据丢失;

方式:由接收端采用滑动窗口的形式,告知发送方允许/停止发包解决TCP丢包问题。

拥塞控制:

作用:为了解决过多的数据注入到网络导致网络崩溃和超负荷问题;

方式:由发送方采用拥塞窗口的形式去判断网络状态,从而采取不同算法执行TCP动态发包解决网络整体质量问题。

慢启动算法:
        发送方先探测网络拥塞程度,并不是一开始就发送大量的数据,发送方会根据拥塞程度增大拥塞窗口。(例如:发2个数据段得到应答,再去尝试发4个数据段...直到找到合适数量的数据段)

1.4常用函数

socket

#include <sys/socket.h>

int socket(int family,int type,int protocol);

  • 功能:创建一个用于网络通信的socket套接字
  • family:协议族(AF_INET(IPv4)、AF_INET6(IPv6)、PF_PACKET(链路层编程))
  • type:套接字类(SOCK_STREAM(流式套接字)、SOCK_DGRAM(数据报式套接字)SOCK_RAW(原始套接字))
  • protocol:协议类别(0、IPPROTO_TCP、IPPROTO_UDP)一般置0
  • 返回值:套接字

bind

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
  • 功能:将socket与本机上的一个端口绑定,随后就可以在该端口监听服务请求
  • sockfd:正在监听端口的套接口文件描述符,通过socket获得
  • addr:需要绑定的IP和端口
  • addrlen:addr的结构体的大小
  • 返回值:失败返回一个小于0的值,成功返回大于等于0的值

listen

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd,int backlog)

  • 功能:listen函数使socket处于被动的监听模式,并为该socket建立一个输入数据队列,将到达的服务请求保存在此队列中,直到程序处理它们。
  • sockfd:传入bind的sockfd。
  • backlog:请求连接队列的最大长度,这个队列指的是多个客户端都请求建立连接时,会把这些连接暂时存入队列中,以便下一步调用accept接受连接。
  • 返回值:成功则返回0,否则-1。

accept

#include <sys/types.h>
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr* addr, socklen_t addrlen);

  • 功能:让服务器接受客户的连接请求。
  • sockfd:经过bind和listen的sockfd。
  • addr:此处addr参数是传出的,函数成功执行后,存的是客户端的IP和端口。
  • addrlen:addr的结构体的大小
  • 返回值:如果成功,则会返回一个非负整数,也就是accepted socket的文件描述符,后续的通信则用这个文件描述符,如果失败则返回-1。

connect

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, struct sockaddr* addr, socklen_t addrlen);

  • 功能:让服务器接受客户的连接请求。
  • sockfd:由socket函数创建的文件描述符。
  • addr:保存服务端的IP和端口
  • addrlen:addr的结构体的大小
  • 返回值:0表示成功,-1表示错误失败。

send

#include <sys/types.h>  

 #include <sys/socket.h>

int send( SOCKET s,    const char FAR *buf,    int len,    int flags );  

  • 功能:数据发送函数。
  • s:指定发送端套接字描述符。
  • buf:指明一个存放应用程序要发送数据的缓冲区。
  • len:要发送的数据的字节数。
  • flags:一般置0。
  • 返回值:n(n大于0意为成功发送 n 个字节;n等于0意为对端关闭连接;n小于0意为出错或者被信号中断或者对端 TCP 窗口太小数据发不出去(send)或者当前网卡缓冲区已无数据可收(recv))

recv

#include <sys/types.h>  

 #include <sys/socket.h>

int recv(int s, void *buf, int len, unsigned int flags);

  • 功能:数据接收函数。
  • s:指定接收端套接字描述符
  • buf:指向一个缓冲区,用于存放接收到的数据。
  • len:缓冲区的长度。
  • flags:一般置0。
  • 返回值:n(n大于0意为成功接收 n 个字节;n等于0意为对端关闭连接;n小于0意为出错)

close 

#include <unistd.h>
int close(int fd);

  • 功能:关闭某个文件描述符
  • fd:socket产生的fd(返回值)

1.5实现tcp通信

tcp通信的简单实现:Linux/tcp_echo_server · swi/c++ - 码云 - 开源中国

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87203.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87203.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gbase8s之MyBatis批量update问题

源代码 <update id"updateDynamicTableData"><foreach collection"mapList" item"map" separator";">UPDATE ${tableName} SET<foreach collection"map" item"value" index"key" separ…

博图SCL中WHILE语句的使用详解及案例

在西门子TIA Portal的SCL&#xff08;结构化控制语言&#xff09;编程中&#xff0c;WHILE循环是处理条件迭代任务的核心工具。它根据布尔表达式动态控制循环执行&#xff0c;适用于不确定循环次数的场景。下面从语法、执行流程、注意事项到实际案例全面解析。 一、WHILE循环基…

简单聊聊JVM中的几种垃圾收集算法

3.4、分代收集算法 分代收集算法&#xff0c;可以看成以上内容的延伸。它的实现思路是根据对象的生命周期的不同&#xff0c;将内存划分为几块&#xff0c;比如把堆空间划分为新生代和老年代&#xff0c;然后根据各块的特点采用最适当的收集算法。 在新生代中&#xff0c;存在…

依赖已导入,已下载,无法使用问题

明明已经导入依赖&#xff0c;却无法使用相关注解 于是&#xff0c;我使用 mvn dependency:tree -Dverbose 来查看是否有依赖冲突 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal on project agileboot…

答题考试系统小程序ThinkPHP+UniApp

ThinkPHPUniapp开发的小程序答题考试系统&#xff0c;支持多种试题类型、多种试题难度、练题、考试、补考模式&#xff0c;提供全部前后台无加密源代码&#xff0c;支持私有化部署. 更新日志 V1.7.1修复一些问题 解决考场成绩列表重复问题&#xff1b; 解决后台材料题选择子…

DHCP服务管理

目录 DHCP协议 DHCP的优势 DHCP的分配方式 应用场景 注意 工作流程 何时更新租约 当客户端重启后 客户端类型 DCHP安装与配置 网络规划&#xff1a; 配置 DHCP 作用域 启动 DHCP 服务 配置路由器 配置路由器网卡 IP 开启 IP 转发&#xff08;确保跨网段通信&…

12.UDP客户端

准备工作 硬件准备&#xff1a;确保你的STM32板子已经正确连接了DP83848网络芯片。 软件设置&#xff1a; 安装好STM32CubeMX用于配置工程。 选择合适的STM32 HAL库版本。 如果可能的话&#xff0c;安装LwIP库支持TCP/IP协议栈。 步骤 1. 使用STM32CubeMX配置项目 打开…

希尔脚本简介及常用命令代码整理

一、Shell 脚本简介 1. 定义 Shell 是用户与操作系统内核交互的桥梁&#xff0c;常见类型有 Bash、Zsh、PowerShell 等。Shell 脚本则是一系列 Shell 命令的集合&#xff0c;通常保存为后缀为.sh 的文本文件。 2. 作用 类别描述自动化重复性任务例如定期备份数据、执行定时…

【人工智能下的智算网络】广域网优化

一、广域网络多路径I/O写的并行路径优化方案 1.1、数学建模 网络拓扑优化​ 1. ​拓扑抽象与路径发现​ ​邻接矩阵建模​&#xff1a; 将网络节点抽象为图顶点 G (V, E)&#xff0c;链路带宽与延迟定义为边权 w(e)。构造邻接矩阵 A&#xff0c;其中元素 A_{ij} 表示节点 …

AI测试开发工程师如何用大模型调用工具:从入门到实践

在软件测试领域&#xff0c;测试工程师常常面临测试用例设计复杂、数据生成繁琐、结果验证耗时等挑战。随着大语言模型&#xff08;LLM&#xff09;的迅速发展&#xff0c;Chat类大模型&#xff08;如GPT、LangChain支持的模型&#xff09;为测试开发提供了一种全新思路——工具…

迁移学习基础

知识的“跨界复用” 你是一位经验丰富的厨师&#xff08;源模型&#xff09;&#xff0c;尤其擅长做意大利菜&#xff08;源任务/源域&#xff09;。现在&#xff0c;老板让你去新开的一家融合餐厅工作&#xff0c;需要你做亚洲菜&#xff08;目标任务/目标域&#xff09;。你…

AI医生24小时在线:你的健康新‘算法监护人

2025年仲夏&#xff0c;中国医疗AI领域迎来爆发式突破&#xff1a;罗湖医院集团率先部署"DeepSeek-腾讯混元"双AI诊疗系统&#xff0c;实现患者15分钟极速就诊闭环&#xff1b;复旦大学研发的微量血液检测技术取得重大突破&#xff0c;仅需数滴血样即可筛查上千种疾病…

Java 中 DataSource-数据源 的基础介绍

Java 中 DataSource-数据源 的基础介绍 一、核心概念解析1.1 数据源&#xff08;Data Source&#xff09;1.2 数据库连接池&#xff08;Connection Pool&#xff09;1.3 二者关系1.4 DataSource 接口 二、DataSource 解决的问题与优势2.1 DataSource 的作用2.2 传统方式的局限性…

Vue + Vite 项目部署 Docker 全攻略:原理、路由机制、问题排查与开发代理解析

Vue Vite 项目部署 Docker 全攻略&#xff1a;原理、路由机制、问题排查与开发代理解析 本文面向希望将 Vue 3 Vite 项目部署到生产环境&#xff08;Docker NGINX&#xff09;并深入理解路由行为、构建机制与常见问题排查的开发者。 &#x1f4e6; 一、项目准备 以 Vue 3 …

Vue3 + TypeScript 使用 v-bind() 在 <style scoped> 中动态设置 CSS 样式值

使用要求&#xff1a; Vue 3.3 <style scoped>&#xff0c;Vue 的 v-bind() 在 CSS 中只支持在 scoped style 或 CSS Modules 中使用v-bind("cssVar") 双引号包裹响应式变量&#xff0c;变量 cssVar 必须是 Vue 的响应式数据&#xff08;如 ref 或 reactive&…

php列表头部增加批量操作按钮,多选订单数据批量微信退款(含微信支付SDK)

index_search.html data-table-id:表格id data-rule:需要传输的列表字段 data-action:控制器方法 <a class="layui-btn layui-btn-primary layui-btn-sm" style=

小程序还没有上线就提示小程序违规,支付失败

如果出现这种情况&#xff0c;一般情况下不是真正的违规&#xff0c;是因为在小程序后台&#xff0c;没有设置订单详情页面的path地址的原因 1.首先看一下&#xff0c;在站内信中是否有相关订单的通知&#xff1a;站内信&#xff08;小程序通知中心&#xff09;查看是否看到 关…

展开说说Android之Glide详解_源码解析

基于上一篇介绍了Glide的使用篇本文分析一下Glide的源码实现&#xff0c;看看我们简单几步就实现的图片展示功能在源码中是怎样完成的。 一、Glide中的核心文件 先逐个介绍一下个人以为的几个核心类&#xff1a;‌ 1、Glide Glide是必经的入口&#xff0c;通过Glide.get(con…

商品中心—6.商品考核系统的技术文档二

大纲 1.基于大数据系统的商品考核数据指标 2.基于商品考核数据指标的商品考核流程 3.商品考核失败后的处理 考核流程的设计 4.商品考核系统数据库模型设计 5.商品考核系统核心接口 6.商品生命周期系统的定时考核任务 6.商品生命周期系统的定时考核任务 (1)定时任务处理…

鸿蒙组件通用事件开发全攻略:从基础交互到工程实践

一、引言&#xff1a;事件系统 —— 构建交互体验的核心枢纽 在鸿蒙应用开发体系中&#xff0c;组件事件系统是连接用户操作与应用逻辑的关键桥梁。从基础的点击交互到复杂的多触点手势&#xff0c;通用事件覆盖了全场景设备的交互需求。本文将系统解构鸿蒙事件体系的核心机制…