socket的状态含义
通过 netstat 命令查看网络状态,其中有一列展示的是 socket 的状态,熟练掌握这些状态的含义有助于连接状态的分析与问题排查。
如下是通过 netstat -natp
命令获取到的一些网络信息
1 | Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name |
可以看到倒数第二列是 socket 的状态,接下来我们就来看下每种状态的含义(下面的数据来自于 netstat 命令的 man page)
CLOSED
socket 已关闭,未在使用中
LISTEN
socket 正在监听连接请求。server 启动时,会先调用 bind
系统调用绑定端口,然后调用 listen
系统调用监听连接请求,此时 ServerSocket 会处于 LISTEN
状态
bind
的方法签名如下:
1 | int bind(int sockfd, const struct sockaddr *addr, |
当通过 socket()
系统调用创建了一个 socket 之后,该 socket 还未分配到地址(address),此时需要调用 bind 命令将 addr 指定的地址绑定到 sockfd 文件描述符所代表的 socket 上
listen
的方法签名如下:
1 | int listen(int sockfd, int backlog); |
listen 系统调用将 sockfd 代表的 socket 标记为 被动的
socket,也就是说这个 socket 用于监听连接请求,当一个连接请求完成3次握手并建立连接后,可以通过 accept 系统调用获取这个连接。其中 sockfd 是一个文件描述符,它指向一个 SOCK_STREAM
或 SOCK_SEQPACKET
类型的 socket。backlog 定义了 待接受连接队列
的最大长度,如果一个连接请求到达后队列已经满了,那么客户端将会收到一个 ECONNREFUSED
,但是如果底层协议支持重传,这个连接请求将会被忽略,客户端会通过重传尝试建立连接。
SYN_SENT
客户端 socket,已经向服务端发送过握手请求,尝试建立连接
SYN_RCVD
服务端 socket,已经接收到了一个来自远端的连接请求
ESTABLISHED
socket 连接已建立完成
CLOSE_WAIT
四次挥手中被动关闭的一方,对方已经发送了关闭请求。本地系统正在等待本地应用程序关闭连接
LAST_ACK
四次挥手中被动关闭的一方,对方已经发送了关闭请求。本地应用已经调用 close() 关闭连接,本地系统正在等待对方的 ack 回复
FIN_WAIT_1
四次挥手中主动关闭的一方,本地应用已经调用了 close 关闭连接,还未收到对方的 ack 回复,系统等待对方关闭半连接
FIN_WAIT_2
四次挥手中主动关闭的一方,本地应用已经调用了 close 关闭连接,并且已经收到了对方的 ack 回复,系统等待对方关闭半连接
CLOSING
本地和对方同时关闭连接,并且本地还未收到对方对 close 请求的 ack
TIME_WAIT
四次挥手中主动关闭的一方,本地应用已经调用了 close 关闭连接,对方也已经关闭了它的半连接,本地系统还需等待一段时间,以确认对方收到了最后一个 ack
- 2021-04-13
本文记录 java BIO 和 NIO 的使用方式,以方便查阅。
- 2021-08-12
在使用 netty 开发网络应用时,通常会设置
ChannelOption.SO_BACKLOG
,不知你有没想过这个参数的作用是什么。 - 2020-01-01
通常情况下,建立一个 TCP 连接需要三次握手,连接建立好之后可以双向同时发送数据。正常断开一个 TCP 连接需要四次挥手。在 TCP 连接建立到断开的过程中,连接双方的状态会发生变化。
- 2022-01-01
转眼又是新的一年,时间过得真是太快了,今天继续来聊聊网络 IO 模型的问题。网络 IO 模型是一个比较抽象的概念,你可以很容易地找到很多介绍网络 IO 模型的文章,也有很多介绍网络 IO 系统调用实现的文章。但是前者往往仅限于抽象的概念介绍,缺少关键的细节。后者则往往介绍过多的细节,让人难以把握住重点。本文将会对比 BIO 和 NIO 两种网络 IO 模型的原理和优缺点,然后通过
recvfrom
系统调用介绍两种 IO 模型在使用上的区别,让你不再被各种高级的类库封装所迷惑。为了防止太多细节干扰你的理解,我将仅挑选关键的代码进行介绍。此外,我会在文章末尾贴出完整的代码,以便你进行测试和验证。 - 2021-01-28
如果你使用过 netty,你一定见过下面两行代码,它们可以说是创建一个 netty server 的标配代码
1
2ChannelFuture future = bootstrap.bind(port).sync();
future.channel().closeFuture().sync();不知道你有没想过这里面的
sync()
的作用是什么,如果去掉会有什么问题?