简体   繁体   中英

sendto() to non existing socket

Im writing an app which sends data over the sockets (from client to server). Im observing very strange behaviour: when i kill server, first send after that kill behaves like server exist. Next one returns EPIPE. Can you explain me why ?

here is strace from client app:

(server not killed)
...
sendto(5, "\0\1\0\0\0\0\0\0000\311\0\0\211A\264R\0\0\0\0\232\377\4\0\0\0\0\0\0\0\0\0"..., 51516, MSG_NOSIGNAL, NULL, 0) = 51516
....
(server killed)
****sendto(5, "\0\1\0\0\1\0\0\0000\311\0\0\272A\264R\0\0\0\0c%\0\0\0\0\0\0\0\0\0\0"..., 51516, MSG_NOSIGNAL, NULL, 0) = 51516,****
(next send after server is killed)
sendto(5, "\0\1\0\0\2\0\0\0000\311\0\0\375A\264R\0\0\0\0d\307\n\0\0\0\0\0\0\0\0\0"..., 51516, MSG_NOSIGNAL, NULL, 0) = -1 EPIPE (Broken pipe)

regards J

TCP does not guarantee that a severed connection will be detected until you try to send some data on it. As soon as you attempt that, you may receive errors back from the network or the send operation may timeout. Because an application-level TCP write only blocks if there's insufficient buffer space available, errors are typically reported at the next operation that can report those errors.

While a severed connection is typically detected immediately, it isn't always, and it is not guaranteed to be. The exact reason can vary based on a lot of factors we don't know. (Was the TCP connection opened by the server application itself? Or did it inherit it or acquire it from another process? Could any other process have a copy of that socket? Did the server call fork with the connection and not close it in the child?)

In TCP, the two directions of a connection operate independently. When the server closes the connection, it sends a message in the server->client direction that says that it is done transmitting; if the client performs a read() or recv() it will get EOF at that point.

However, this message says nothing about the client->server direction. TCP doesn't provide any way for the server to tell the client that it is not willing to read any more data. So there's no way for the client to know that a send will fail before it tries to send it.

When the server receives that new message from the client, if there's no server process still trying to read from the connection, the server sends a RST message to the client. This is asynchronous -- the sendto() call on the client has already returned (in fact, it returns immediately after copying the data into a kernel buffer, before anything is sent to the network). When the client TCP stack receives the RST message, it sets a error flag on the socket, and the next time the client tries to do anything with the socket it gets an EPIPE error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM