Linux Socket编程:当客户端套接字在通信过程中断开时,服务器套接字会发生什么

时间:2016-10-20 06:20:08

标签: linux sockets networking tcp network-programming

假设通过网络在两个套接字之间建立tcp连接。      一个是服务器,另一个是客户端。

  1. 客户端关闭时会发生什么?从socket编程的角度来看。 假设我们为此编写了自己的套接字程序。

  2. TCP堆栈中会发生什么?

  3. 谁来处理这些情况? TCP堆栈或Socket程序必须有自己的智能吗?

    请指出我的帖子,如果这个重复。

    • 感谢

2 个答案:

答案 0 :(得分:1)

What happen when client is down ? from socket programming perspective. Assume that we have written our own socket program for this.

By "client is down", I'm assuming you mean something like, "someone yanked the client machine's Ethernet cord out of the wall", i.e. the client computer has suddenly and completely lost communication with the server (and not "the client program crashed/exited", which is a different and simpler situation since in that case the client computer's OS is still available to explain to the server what happened)

In that case, what will happen is that the server will stop receiving any packets back from the client. That means it won't receive any more data sent by the client (obviously), but it also means that the server won't receive any ACK packets back in response to data it sends to the client, either.

From a socket programming perspective, assuming the server is trying to send data to the client, the socket's outgoing-data-buffer will fill up with data, at which point the server will not be able to write()/send() any more data to that socket. That is, if the socket is in blocking mode, the next call to write()/send() will block, or if the socket is in non-blocking mode, the call will error out immediately with errno EWOULDBLOCK. That state will last usually for a while (e.g. 30 seconds to several minutes), until the server's TCP protocol logic finally gets tired of fruitlessly resending packets and gives up on the client ever responding; at which point the server's TCP stack will unilaterally close the connection. When that happens, any calls to send() or write() on the socket will result in a SIGPIPE signal being emitted (possibly aborting the server program, if you don't have a signal-handler installed), or if you've done a signal(SIGPIPE, SIG_IGN), then the write()/send() call will instead just return -1 and set errno to EPIPE.

If the server wasn't trying to send any data to the client, on the other hand, then the server has no way of knowing that the client has gone away, in which case it might be several hours (or never, depending on whether you've enabled TCP keepalive on the socket or not) before the server does anything. (That is why many TCP-based programs periodically send dummy data over an idle TCP socket, just so they will find out sooner rather than later that the connectivity has gone away)

What happen in TCP stack ?

Inside the TCP stack there is logic that (conceptually speaking) watches the outgoing-data-buffers of each TCP socket in the system, and whenever there are bytes of data present in a socket's buffer, the TCP stack is trying to get that data delivered to the remote host. It does that by sending TCP packets, and if it doesn't get acknowledgements from the remote peer that those packets were received, after a little while it will try to send them again. As acknowledgements continue not to be received, it will wait longer and longer for each retry, and/or reduce the rate at which packets are sent, in the hopes of reducing network congestion enough for some data to get through (remember that the server has no way of knowing why the client isn't responding). Eventually it will decide that there is no point in continuing, and then it will give up and close the TCP connection.

Who will handle these situation ? Either TCP stack or Socket program has to have its own intelligence ?

Both layers have to handle it. The TCP stack's send-more-TCP-data routines handle the detection of a dead socket, and communicate that condition to the socket program (as described above), and then it is up to the socket program to handle the dead connection gracefully (typically by close()-ing the broken TCP socket and continuing on without it).

答案 1 :(得分:0)

如果启用TCP_KEEPALIVE,则...

...最终操作系统将确定另一方不再可用,并且您的套接字将变为可读并且读取将返回错误代码,以告知您套接字已关闭。

http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html

int keepalive = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive , sizeof(keepalive ));

另外,keepalive会确保您的NAT不会丢弃原本未使用但仍然有效的连接。