1、客户端(主动)
- close —> syn_sent —> established —> fin_wait1 —> fin_wait2 —> time_wait —> 2(msl)
- close —> syn_sent —> established —> fin_wait1 —> closing —> time_wait —> 2(msl)
- close —> syn_sent —> established —> fin_wait1 —> time_wait —> 2(msl)
- msl:maximum segment lifetime
- msl:maximum segment lifetime
2、服务端(被动)
- close —> listen —> syn_rcvd —> established —> close_wait —> last_ack —> close
- close —> listen —> syn_rcvd —(RST)—> listen
- 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可用状态。
3、在Server—->Client通讯环境中,结束Client进程
- FIN_WAIT1状态时间很短,后续接收报文不同,状态转变也不一样
- FIN_WAIT1 —(ACK)–> FIN_WAIT2 —(FIN)–> TIME_WAIT —(ACK)–>2(MSL)
- FIN_WAIT1 —(FIN)–> CLOSING —(ACK)–> TIME-WAIT —(ACK)–>2(MSL)
- FIN_WAIT1 —(ACK+FIN)–> TIME_WAITGG —(ACK)–>2(MSL)
4、在Server—->Client通讯环境中,结束Server进程
- Server进程结束前发送FIN报文,通讯状态由ESTABLISHED ——> FIN_WAIT1
- Client收到FIN报文后,状态由ESTABLISHED ——> CLOSE_WAIT,回复ACK报文
- Server收到ACK报文后,状态由FIN_WAIT1 ——> FIN_WAIT2
5、shutdown函数
- 相比close函数
- 可以只关闭读(SHUT_RD)、写(SHUT_WR)或读写(SHUT_RDWR)的操作;
- 不考虑文件描述符的引用计数,直接关闭文件描述符。
#include <sys/socket.h>
int shutdown(int sockfd, int how);
DESCRIPTION
The shutdown() call causes all or part of a full-duplex connection on the socket associated with sockfd to be shut down. If how is SHUT_RD, further receptions will be disallowed. If how is SHUT_WR, further transmissions will be disallowed. If how is SHUT_RDWR, further receptions and transmissions will be disallowed.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
6、setsockopt函数
- 为解决端口复用的问题,可以使用setsockopt函数
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
e.g
int optval = 1;
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));