SO_LINGER 选项 与 shutdown 函数

 http://www.360doc.com/content/14/0214/15/9490170_352463397.shtml

SO_LINGER 选项用来指明关闭基于连接的 socket 时的行为。默认,close 函数会立即返回,但当 socket 发送缓冲区残留数据时,close 函数向缓冲区中写入 FIN 后,同样会立即返回,但 TCP 将会尽力发送完这些数据。

SO_LINGER 选项 与 shutdown 函数_第1张图片




如果要改变 close 函数的默认行为,就需要 SO_LINGER 选项。相关的数据结构如下:

struct linger {
  int   l_onoff;        /* 0=off, nonzero=on */
  int   l_linger;       /* linger time, POSIX specifies units as seconds */
};



1. l_on

off 字段设为 0 时, 选项被关闭,close 时为默认行为。

2. l_on off 非 0 , 而 l_linger 设为 0 时,close 清空发送缓冲区的数据,并向缓冲区中写入 RST ,然后返回。 这样可以避免进入 TIME_WAIT 状态。

3. l_on off 和 l_linger 均不为 0 ,close 阻塞直到:
1) 缓冲区中的数据以及 FIN 发送出去,并得到对等端的确认。(图 7.8)
2)l_linger 设置的时间超时。(图 7.9)
而 后,close 返回。(当然非阻塞模式下,close并不等待数据发送完成或者超时,而是立即返回)

SO_LINGER 选项 与 shutdown 函数_第2张图片


SO_LINGER 选项 与 shutdown 函数_第3张图片


这种情况下需要注意的是,要检查 close 函数的返回值,在数据以及FIN得到确认之前如果超时的话,close 返回 EWOULDBLOCK ,并清空缓冲区。另外 TCP 向对等端发送一个 RST 。
当然·,close 成功返回只是告诉我们对等端 TCP 成功接收到数据,并不能告诉我们对等端 应用进程 是否成功接收到数据。 (如果不设置 SO_LINGER 选项, 我们无法知道发出的数据是否被对等端确认)

接着上面的话题,如果想知道对等端 应用进程 是否接收到数据,可以调用 shutdown 函数(参数为 SHUT_WR),代替 close 。然后调用 read 函数。 正常情况下,read 应该读到 对等端发过来的 FIN,并返回 0 。

SO_LINGER 选项 与 shutdown 函数_第4张图片


另外一种确认对等端 应用进程 接受到数据的方法是 “应用程序级别的确认”, 如下,客户进程发送数据之后,并读取 1 个字节的确认数据。
char  ack;

Write(sockfd, data, nbytes);       /* data from client to server */
n = Read(sockfd, &ack, 1);         /* wait for application-level ACK */

服 务进程读到客户端发来的数据后,写回一个 “应用程序级别的确认” 。


nbytes = Read(sockfd, buff, sizeof(buff)); /* data from client */
         /* server verifies it received correct
            amount of data from client */
Write(sockfd, "", 1);           /* server's ACK back to client */

这 样,我们就可以保证,当客户端 read 返回时,服务进程已经读到了客户端发送的数据。(这里假定服务进程知道客户端一次发送多少数据)


shutdown 函数、close 函数、以及 SO_LINGER 总结

SO_LINGER 选项 与 shutdown 函数_第5张图片

 

你可能感兴趣的:(SO_LINGER 选项 与 shutdown 函数)