今天上午 回顾了 TCP/IP编程之select函数详解 ,发现还有问题。进行总结
查看 man send
On success, these calls return the number of characters sent
这个没说明 是不是0呢?
答:
但是通过实践经验 send 表示 发送到本地缓冲区,数据不一定发送过去, 还有第二次概念 因此推断 不会返回0.
像已经关闭的tcp连接,send 数据 第一次会触发RST。这个RST怎么检测,依靠send吗?第二次 send 返回管道信号,如何检测 依靠send吗?
答:
但是内核可以控制send 不发送管道信号。
但是liunx 提供一个send参数
MSG_NOSIGNAL (since Linux 2.2)
Requests not to send SIGPIPE on errors on stream oriented sockets when the other end breaks the connection. The EPIPE error is still returned.
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
EPIPE
The local end has been shut down on a connection oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.
EAGAIN or EWOULDBLOCK
read 三个参数:
ssize_t read(int fd, void *buf, size_t count);
https://linux.die.net/man/2/read
send:四个参数
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
什么是RST,有什么意义?
答:
RST 是个flag
https://www.ietf.org/rfc/rfc793.txt TCP Header Format
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Control Bits: 6 bits (from left to right):
URG: Urgent Pointer field significant
ACK: Acknowledgment field significant
PSH: Push Function
RST: Reset the connection
SYN: Synchronize sequence numbers
FIN: No more data from sender
RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。就像上面说的一样,发送RST包关闭连接时,不必等缓冲区的包都发出去(不像上面的FIN包),直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。
TCP处理程序会在自己认为的异常时刻发送RST包。例如,A向B发起连接,但B之上并未监听相应的端口,这时B操作系统上的TCP处理程序会发RST包。
又比如,
AB正常建立连接了,正在通讯时,A向B发送了FIN包要求关连接,B发送ACK后,网断了, A通过若干原因放弃了这个连接(例如进程重启)。网通了后, B又开始发数据包,A收到后表示压力很大,不知道这野连接哪来的, 就发了个RST包强制把连接关了, B收到后会出现connect reset by peer错误。
根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时, 系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。
又或者当一个进程向某个已经收到RST的socket执行写操作是, 内核向该进程发送一个SIGPIPE信号。该信号的缺省学位是终止进程,因此进程必须捕获它以免不情愿的被终止
异常关闭一个连接对应用程序来说有两个优点:
(1)丢弃任何待发的已经无意义的 数据,并立即发送RST报文段;
(2)RST的接收方利用关闭方式来 区分另一端执行的是异常关闭还是正常关闭 (通过read操作的返回值,正常的返回读取字节或者堵塞,RST的返回错误)read
Return Value On success, the number of bytes read is returned (zero indicates end of file) On error, -1 is returned, and errno is set appropriately
https://zhuanlan.zhihu.com/p/149265232
直接释放连接:
在交互的双方中的某一方长期未收到来自对方的确认报文,则其在超出一定的重传次数或时间后,会主动向对端发送reset报文释放该TCP连接
TCP A TCP B
1. ESTABLISHED ESTABLISHED
2. (Close)
FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> --> CLOSE-WAIT【被动关闭,只要对方发送closed】
3. FIN-WAIT-2 <-- <SEQ=300><ACK=101><CTL=ACK> <-- CLOSE-WAIT
4. (Close)
TIME-WAIT <-- <SEQ=300><ACK=101><CTL=FIN,ACK> <-- LAST-ACK[等待ack,CLOSE-WAIT 需要确认的。]
5. TIME-WAIT --> <SEQ=101><ACK=301><CTL=ACK> --> CLOSED
6. (2 MSL)
CLOSED
Normal Close Sequence
Figure 13.
TCP A TCP B
1. ESTABLISHED ESTABLISHED
2. (Close) (Close)
FIN-WAIT-1 --> <SEQ=100><ACK=300><CTL=FIN,ACK> ... FIN-WAIT-1
<-- <SEQ=300><ACK=100><CTL=FIN,ACK> <--
... <SEQ=100><ACK=300><CTL=FIN,ACK> -->
3. CLOSING --> <SEQ=101><ACK=301><CTL=ACK> ... CLOSING
<-- <SEQ=301><ACK=101><CTL=ACK> <--
... <SEQ=101><ACK=301><CTL=ACK> -->
4. TIME-WAIT TIME-WAIT
(2 MSL) (2 MSL)
CLOSED CLOSED
Simultaneous Close Sequence
Figure 14.
4,在交互的双方中的某一方长期未收到来自对方的确认报文,则其在超出一定的重传次数或时间后,会主动向对端发送reset报文释放该TCP连接
3,接收端收到TCP报文,但是发现该TCP的报文,并不在其已建立的TCP连接列表内,则其直接向对端发送reset报文
An interesting alternative case occurs when TCP A crashes and TCP B tries to send data on what it thinks is a synchronized connection.
1,客户端尝试与服务器未对外提供服务的端口建立TCP连接,服务器将会直接向客户端发送reset报文。