TCP传输控制协议

news/2024/10/7 22:18:45

网络编程

TCP传输控制协议

传输层中最为常见的两个协议分别是传输控制协议TCP(Transmission Control Protocol)和用户数据报协议UDP(User Datagram Protocol)

一、TCP协议的特点:TCP是面向连接的,端对端(一对一)的可靠的协议,可修复损坏数据,全双工的连接

1.TCP协议判断数据是否损坏的方式是给每个数据段都添加校验和,接收端收到数据段进行校验,如果校验失败则丢弃已经损坏的数据段,也并不会进行确认应答,所以TCP协议会再次传输数据段,且修复损坏、出现丢失、出现重复、到达无序的数据。

2.另外,接收端每次接收到数据之后必须发送确认应答(ACK),如果在超时时间内没有发送应答信号(ACK),则TCP协议会认为数据没有送达,则会重新发送数据。

3.因为通信可能是建立在不可靠的网络中以及网络层不可靠的传输机制,所以TCP协议中采用了一种*基于时钟的序列号握手机制*实现双方的有效连接。

二、TCP报首的格式

image

源端口号:发送端的进程端口号,两个字节。

目标端口:接收端的进程端口号,两个字节。

序列号SEQ:序列号主要是为了解决网络包乱序的问题,指的是数据段中的第一个字节的序列号,如果数据段中存在SYN标志位,则序列号为初始序列号(ISN),那么数据段中的第一个字节的序列号等于 ISN + 1。

控制位:SYN同步请求连接;确认应答号ACK;结束标志FIN。

头部长度:用于表示数据的开始位置,至少是20字节。

校验和:用于解决数据出现丢包、重复、无序、损坏的问题,接收端收到数据段会进行校验,当校验失败时会丢弃损坏的数据段。

窗口号:用于表示接收端剩余空间的值。

三、TCP的通信流程

采用C/S模式可以把双方分为主动连接端/客户端(client)和被动连接端/服务端(server)。
image

1) socket()函数:int socket(int domain, int type, int protocol);

1.参数 int domain(协议族), int type(socket的类型), int protocol(协议)

2.返回值 套接字的文件描述符。

3.例子 socket(AF_INET,SOCK_STREAM,0);

客户端(client)

1) connect()函数:int connect(int sockfd, const struct sockaddr addr, socklen_t addrlen);

1.参数 int sockfd(文件描述符), const struct sockaddr *addr(目标主机的地址), socklen_t addrlen(目 标主机的地址结构的大小,可用sizeof计算)

2.返回值 成功则返回0,失败则返回-1,一般情况下只能成功连接一次。

3.注意 如果调用connect()函数连接目标主机失败,则调用方的套接字状态是未指定的,所以应该关闭 套接字,并重新创建一个新的套接字,然后再次连接即可。

2) send()函数:ssize_t send(int sockfd, const void buf, size_t len, int flags);

1.参数 int sockfd(文件描述符),const void *buf(待发送数据的缓冲区), size_t len(待发送数据的长度), int flags(发送标志)

2.返回值 成功返回实际发送的字节个数,失败返回-1并且会返回错误码。

3.注意 ①send()函数只能用于套接字处于连接的状态。

​ ②另外,如果要发送的数据的不适合套接字的发送缓冲区,则send()函数通常会阻塞,除非套 接字设置为非阻塞模式(如果套接字处于非阻塞模式,则send()函数会调用失败)。

​ ③发送端发送的数据会暂存在接收端的内核缓冲区中,如果接收端一直不接收数据,则会导致 接收缓冲区满,这样发送端调用send()函数继续发送数据时也会阻塞。

服务端(server)

1) listen()函数:int listen(int sockfd, int backlog);

1.参数 int sockfd(被设置为监听状态的套接字),int backlog(等待接受连接的客户端的最大长度)。

2.返回值 成功则返回0,失败则返回-1。

3.注意 listen()函数是不会阻塞的。

2) accept()函数:int accept(int sockfd, struct sockaddr addr, socklen_t addrlen);

1.参数 int sockfd(被设置为监听状态的套接字), struct sockaddr *addr(对方主机地址的结构指针), socklen_t *addrlen(对方主机的地址信息长度)

2.返回值 成功会返回一个新的套接字文件描述符,失败则返回-1。

3.注意 accept()函数会从等待连接的队列中提取第一个客户端进行连接,如果此时等待队列中没有等 待连接的客户端,则accept()函数会阻塞,直到等待队列中存在客户端请求。

3) recv()函数:ssize_t recv(int sockfd, void buf, size_t len, int flags);

1.参数 int sockfd(accept()函数的返回的套接字), void *buf(接收到的数据要存储的缓冲 区), size_t len(要接收的数据的大小), int flags(接收标志)

2.返回值 成功返回接收到的字节个数,失败则返回-1,如果客户端已经关闭连接,则返回值为0,如果 没有收到数据,则recv()函数会默认阻塞,直到有数据到达。

四、TCP的握手机制

TCP的三次握手是在客户端调用connect()期间和服务器调用accept()期间才会发生的。
image

五、TCP的数据缓冲区

1.对于TCP通信而言,是具有发送缓冲区和接收缓冲区的,发送端具有发送缓冲区,接收端具有接收缓冲区。想要设置接收缓冲区的大小,则需要通过设置套接字的属性选项实现,Linux系统中提供了两个函数接口来获取和设置套接字的属性选项,分别是getsockopt()和setsockopt()。
image
**2)getsockopt()函数:int getsockopt(int sockfd,int level,int optname,void optval,socklent optlen);

*3)setsockopt()函数:int setsockopt(int sockfd, int level, int optname, const void optval, socklen_t optlen);

1.参数 int sockfd(套接字对应的文件描述符)

​ int level(选项对应的协议级别,一般为SOL_SOCKET)

​ int optname(属性名称,例如为接收缓冲区则填SO_RCVBUF,详细如下图)

​ void *optval(设置的选项值)

​ socklent *optlen(选项值的长度,数据类型的大小)

2.返回值 成功返回0,失败返回-1并且会返回错误码。

3.注意 如果打算设置TCP接收缓冲区大小,应该在调用listen()函数之前进行设置才会生效!!!
image
4)设置TCP的接收缓冲区为某个固定值

可以把TCP接收缓冲区理解为一个水池,在水到达水位线时才能输出。在Linux系统中缓冲区初始化为1,且只有接收缓冲区允许被修改。
image

六、TCP的OOB(Out of Band)带外数据

通过特殊的标志位,让数据可以不受缓冲区和水位线的限制,可以优先读取,但是带外数据每次只能发送一个字节,可以发送多次,由于recv()函数和send()函数的第4个参数才可以指定MSG_OOB标志,所以紧急带外数据只能通过recv()和send()这两个函数进行收发。带外数据也是通过内核缓冲区发送出去,所以接收端接收到之后也需要从内核缓冲区中读取出来。并且接收端需要对SIGURG信号进行注册,但是由于信号触发之后会中断程序执行,应该确保信号响应接口只是完成接收动作,应该确保响应函数立即结束
image

七、套接字的超时控制

1)服务器接受客户端的连接请求成功建立连接外还存在两种情况会导致程序逻辑异常:

1.服务器默认设置是阻塞模式,服务器运行之后如果一直没有客户端发起连接请求,此时服务器会阻塞在accept()函数的位置。

2.把服务器的套接字设置为非阻塞模式,如果服务器没有监听到有客户端发起连接请求,则服务器的accept()函数会立刻返回。

2)解决方案

1.避免长时间阻塞应使用setsockopt设置套接字为非阻塞模式并且设置超时机制,如果超时时间设置为0,则操作永远不会超时。

2.如果要设置超时时间,需要利用名称叫做struct timeval的结构体,结构体有2个成员,成员tv_sec指的是秒数,成员tv_usec指的是微秒数。
image

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

NPU与超异构计算杂谈

NPU与超异构计算杂谈 NPU 基础 近年来,随着人工智能技术的飞速发展,AI 专用处理器如 NPU(Neural Processing Unit)和 TPU(Tensor Processing Unit)也应运而生。这些处理器旨在加速深度学习和机器学习任务,相比传统的 CPU 和 GPU,它们在处理 AI 任务时表现出更高的效率和…

植物大战僵尸杂交版 官方版(作者:b站潜艇伟伟迷) 植物大战僵尸杂交版v2.0.88安装程序.exe

植物大战僵尸杂交版 官方版(作者:b站潜艇伟伟迷) 植物大战僵尸杂交版v2.0.88安装程序.exe阿里云盘链接: https://www.alipan.com/s/HgmmLFjHzj7 提取码: 15yc 【点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。】夸克网盘…

网络编程知识点

网络编程 两台主机的进程实现通信的方式 同一台主机中的实现进程间通信的方式有很多,比如管道、信号、消息队列、信号量集、共享内存等,如果现在需要两台主机间的进程实现数据传输,则想要用到套接字文件(socket)的,它的作用则是用于实现不同主机中的进程间通信的。 IP协议 …

MySQL存储

MySQL存储关系型数据库是基于关系模型的数据库,而关系模型是通过二维表来保存的,所以它的存储方式就是行列组成的表,每一列是一个字段,每一行是一条记录。表可以看作某个实体的集合,实体之间存在联系需要表与表之间的关联关系来体现,如主键外键的关联关系。多个表组成一个…

VMware-Ubuntu20.04配置双网卡解决远程连接的2种场景

需求场景环境:VMware Workstation下的虚拟机Ubuntu20.04 LTS 需求1:网卡1:桥接模式,在物理局域网与宿主机拥有同网段的IP,便于局域网通信 需求2:网卡2:NAT模式,假如不在家中局域网,宿主机未连入局域网时,Ubuntu使用NAT模式连接宿主机,共享使用宿主机网络,此时需要宿…

MySQL-12.数据库其他调优策略

C-12.数据库其他调优策略 1.数据库调优的措施1.1 调优的目标尽可能节省系统资源,以便系统可以提供更大负荷的服务。(吞吐量更大) 合理的结构设计和参数调整,以提高用户操作响应的速度。(响应速度更快) 减少系统的瓶颈,提高MySQL数据库整体的性能。1.2 如何定位调优问题 不过…

2024/06/09

学习时长:4.5小时 代码行数:121行 博客数量:1篇 今日主要学习了调用阿里云api来完成发送短信验证码 首先要在阿里云开通短信服务 然后申请资质,创建模板。 然后使用api使用 然后就会生成对应的sdk示例// This file is auto-generated, dont edit it. Thanks. package dem…

m基于PSO粒子群优化的LDPC码OMS译码算法最优偏移参数计算和误码率matlab仿真

1.算法仿真效果 matlab2022a仿真结果如下:2.算法涉及理论知识概要Offset Min-Sum(OMS)译码算法是LDPC码的一种低复杂度迭代解码方法,它通过引入偏移量来减轻最小和算法中的量化效应,从而提高解码性能。当应用粒子群优化(PSO)来计算OMS译码算法中的最优偏移参数时,目标是…