Linux网络编程4——网络编程基础2

学习视频链接

黑马程序员-Linux网络编程_哔哩哔哩_bilibili黑马程序员黑马程序员-Linux网络编程, 视频播放量 241433、弹幕量 7600、点赞数 1627、投硬币枚数 744、收藏人数 9498、转发人数 588, 视频作者 可爱的小飞猪, 作者简介 腹有诗书气自华,相关视频:linux全套教程【黑马】,黑马程序员-Linux系统编程,超细超强Linux网络编程,【黑马程序员】B站讲的最透彻的Jenkins教程,太厉害了 已跪!终于有人能把Jenkins讲的明明白白了(持续集成工具Jenkins),C++项目实战,C/C++开源项目推荐,帮助大家从学习走向实践!研究开源项目是获得项目经验的绝好途径!,每个程序员必看的TCP/IP协议、socket通信、IO、Linux操作系统,这里全有~,最快Linux入门教程+最新学习路线!程序员必备组合拳,千锋教育嵌入式物联网教程800集,C语言编程入门到精通(物联网开发工程师必备视频),【并发】IO多路复用select/poll/epoll介绍https://www.bilibili.com/video/BV1iJ411S7UA?p=45&spm_id_from=333.1007.top_right_bar_window_history.content.click

目录

一、TCP状态转移图

1.1 总览

1.2 分析三次握手主动端

1.3 分析四次挥手主动端

1.4 被动端

1.5 所有状态简介

二、2MSL和端口复用

2.1 2MSL

2.2 端口复用

三、半关闭


一、TCP状态转移图

1.1 总览

Linux网络编程4——网络编程基础2_第1张图片

1.2 分析三次握手主动端

Linux网络编程4——网络编程基础2_第2张图片

一开始服务端和客户端都是 CLOSE 的状态。客户端是主动方发送 SYN 消息,服务端是被动方接收到 SYN 消息,客户端发完 SYN 消息后变成 SYN_SEND 状态。服务端 ACK 消息应答客户端的 SYN,同时把自己的 SYN 发送过去。客户端接收到 SYN 和 ACK,发送应答 SYN 消息的 ACK 消息。发送完 ACK 消息,客户端的状态就变成了 ESTACLISHED

使用程序分析上述过程:

Linux网络编程4——网络编程基础2_第3张图片

右上角的窗口中查询相应的端口号,发现三个 TCP

第一个 TCP 是服务器用于监听的,处于 LISTEN 状态

第二个 TCP 是用于通信的服务器,处于 ESTACLISHED 状态

第三个 TCP 是用于通信的客户端,处于 ESTACLISHED 状态

1.3 分析四次挥手主动端

Linux网络编程4——网络编程基础2_第4张图片

一开始主动提出关闭连接方和被动方都是 ESTACLISHED 状态,主动提出关闭连接的一端在左边,主动方发送 FIN,发送完消息后主动方变成 FIN_WAIT_1 状态。被动方同意的话会回信 ACK,主动方收到信息 ACK 后变成 FIN_WAIT_2 状态 (也就是半关闭状态)

然后被动方发送 FIN 给主动方,主动方收到后发送 ACK。主动方发完 ACK 消息后,主动方的状态变成 TIME_WAIT 状态。TIME_WAIT 状态不会立即变成 CLOSE,要经历 2MSL 时长才会变成 CLOSE 状态 (MSL 是最长报文生存时间,2MSL 大约四十秒)

下图中,客户端就是处于等待的状态

1.4 被动端

Linux网络编程4——网络编程基础2_第5张图片

1.5 所有状态简介

CLOSED:表示初始状态。

LISTEN:该状态表示服务器端的某个SOCKET处于监听状态,可以接受连接。

SYN_SENT:这个状态与SYN_RCVD遥相呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,随即进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。

SYN_RCVD: 该状态表示接收到SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂。此种状态时,当收到客户端的ACK报文后,会进入到ESTABLISHED状态。

ESTABLISHED:表示连接已经建立。

FIN_WAIT_1:  FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。区别是:

FIN_WAIT_1状态是当socket在ESTABLISHED状态时,想主动关闭连接,向对方发送了FIN报文,此时该socket进入到FIN_WAIT_1状态。

FIN_WAIT_2状态是当对方回应ACK后,该socket进入到FIN_WAIT_2状态,正常情况下,对方应马上回应ACK报文,所以FIN_WAIT_1状态一般较难见到,而FIN_WAIT_2状态可用netstat看到。

FIN_WAIT_2:主动关闭链接的一方,发出FIN收到ACK以后进入该状态。称之为半连接或半关闭状态。该状态下的socket只能接收数据,不能发。

TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,等2MSL后即可回到CLOSED可用状态。如果FIN_WAIT_1状态下,收到对方同时带 FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

CLOSING: 这种状态较特殊,属于一种较罕见的状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

CLOSE_WAIT: 此种状态表示在等待关闭。当对方关闭一个SOCKET后发送FIN报文给自己,系统会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,察看是否还有数据发送给对方,如果没有可以 close这个SOCKET,发送FIN报文给对方,即关闭连接。所以在CLOSE_WAIT状态下,需要关闭连接。

LAST_ACK: 该状态是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,即可以进入到CLOSED可用状态。

二、2MSL和端口复用

2.1 2MSL

为保证最后一个 ACK 能成功被对端接收。(等待期间,对端没收到我发的 ACK,对端会再次发送  FIN 请求)

但是面临的问题是服务端关闭后短期内不能再启动了。因为要等 2MSL 时长,在此期间端口是被占用了,端口是写死的,所以不能启动

2.2 端口复用

因为有 2MSL 时长,所以有端口复用这一概念。我们现在可以设置无需等待直接复用这个端口,需要使用以下函数

int opt = 1;  // 设置端口复用
setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (* void)&opt, sizeof(opt));

Linux网络编程4——网络编程基础2_第6张图片

三、半关闭

通信双方中,只有一端关闭通信 —— FIN_WAIT_2

可以使用的函数:close(cfd)、shutdown(int fd, int how);

how: SHUT_RD 关闭读端;SHUT_WR 关闭写端;SHUT_RDWR 关闭读写端

close 和 shutdown 的区别

close 是文件描述符减 1

shutdown 是文件描述符 全部关闭

Linux网络编程4——网络编程基础2_第7张图片

你可能感兴趣的:(linux,网络,服务器,运维)