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 总览

1.2 分析三次握手主动端

4ec66628fd3b4052ab305b68fe4c9234.png

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

使用程序分析上述过程:

a0acf9c5120740a5b02eb44eca5e6fef.png

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

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

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

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

1.3 分析四次挥手主动端

96f254f6773c4ec5afba33965dc6d2ff.png

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

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

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

1da63804e37f4ced8d43811b52a28f10.png

1.4 被动端

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));

三、半关闭

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

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

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

close 和 shutdown 的区别

close 是文件描述符减 1

shutdown 是文件描述符 全部关闭

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

herb.dr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值