前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >60秒问答:系统调用之send函数

60秒问答:系统调用之send函数

作者头像
程序员小王
发布2021-07-22 10:45:15
6990
发布2021-07-22 10:45:15
举报
文章被收录于专栏:架构说架构说架构说

今天上午 回顾了 TCP/IP编程之select函数详解 ,发现还有问题。进行总结

问:系统调用函数send 返回值 可能是0吗?

查看 man send 
On success, these calls return the number of characters sent
这个没说明 是不是0呢?

答:

  • 不可能 【推测】
  • 因为,read 返回 0表示正常结束,

但是通过实践经验 send 表示 发送到本地缓冲区,数据不一定发送过去, 还有第二次概念 因此推断 不会返回0.

问:send场景:

像已经关闭的tcp连接,send 数据 第一次会触发RST。这个RST怎么检测,依靠send吗?第二次 send 返回管道信号,如何检测 依靠send吗?

答:

  • 解决方案1:第一次会触发RST,send无法解决?非阻塞模型下,select或者epoll会返回sockfd可读,应用层对其进行读取时, 收到RST的client端,如果调用read函数,读取,是返回RST错误的
  • 解决方案2:可以 第二次 send 返回管道信号 管道信号是异步的,信号是程序无法try catch的 需要信号处理函数。

但是内核可以控制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报文,不需要进行ack,另一端根本不进行确认。收到RST的一方将终止该连接

什么是RST,有什么意义?

答:

什么是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

EAGAIN or EWOULDBLOCK EINTR EBADF fd is not a valid file descriptor or is not open for reading.

https://zhuanlan.zhihu.com/p/149265232

TCP异常终止(reset报文) 场景

直接释放连接:

5,有些应用开发者在设计应用系统时,会利用reset报文快速释放已经完成数据交互的TCP连接,以提高业务交互的效率,如下图所示:

在交互的双方中的某一方长期未收到来自对方的确认报文,则其在超出一定的重传次数或时间后,会主动向对端发送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报文

2,客户端和服务器的某一方在交互的过程中发生异常(如程序崩溃等),该方系统将向对端发送TCP reset报文,告之对方释放相关的TCP连接 【服务crash但是 主机和网络正常】

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报文。

塔山

  • https://blog.csdn.net/polarbearboy/article/details/6691405
  • http://blog.sina.com.cn/s/blog_6c2e6f1f0100ok4y.html
  • http://bbs.chinaunix.net/thread-838813-1-1.html
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Offer多多 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问:系统调用函数send 返回值 可能是0吗?
  • 问:send场景:
  • 问:接受到RST报文,不需要进行ack,另一端根本不进行确认。收到RST的一方将终止该连接
    • 什么是RST?
      • 对发送和和接受方都有意义。
      • EAGAIN or EWOULDBLOCK EINTR EBADF fd is not a valid file descriptor or is not open for reading.
        • TCP异常终止(reset报文) 场景
          • 5,有些应用开发者在设计应用系统时,会利用reset报文快速释放已经完成数据交互的TCP连接,以提高业务交互的效率,如下图所示:
          • 2,客户端和服务器的某一方在交互的过程中发生异常(如程序崩溃等),该方系统将向对端发送TCP reset报文,告之对方释放相关的TCP连接 【服务crash但是 主机和网络正常】
      • 塔山
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档