If I send some data then immediately close the socket, will the other end receive the data? - sockets

For .NET framework System.Net.Sockets.Socket, if I send some data then immediately close the socket, will the other end receive the data?
If not, is there a way for me to close the socket only after the other end receives the data?

WebSocket over HTTP works by establishing a TCP/IP connection, which requires the clients to sends an upgrade header in the payload to the server, and if the server can establish the create a WebSocket connection, it will reply with a HTTP 101 Switching Protocols response. Once the connection is established successfully, you can send data back and forth.
Interesting enough, requesting to close the connection also requires you to send a frame, which means you are also sending data to the server. Not even that, to properly close the connection, the sever also needs to respond with the same closing frame, once that happens the TCP connection is terminated and you can no longer send data.
What that means in your case is the server would receive the data you had sent before sending the close request frame.
You can read more about the details of frame, http headers, etc in the protocol RFC https://tools.ietf.org/html/rfc6455

Related

How does HTTP/1.1 solve the TCP reset problem?

I am trying to understand the TCP reset problem mentioned in RFC 7230: HTTP/1.1 Message Syntax and Routing, § 6.6:
6.6. Tear-down
The Connection header field (Section 6.1) provides a "close"
connection option that a sender SHOULD send when it wishes to close
the connection after the current request/response pair.
So HTTP/1.1 has persistent connections, meaning that multiple HTTP request/response pairs can be sent on the same connection.
A client that sends a "close" connection option MUST NOT send further
requests on that connection (after the one containing "close") and
MUST close the connection after reading the final response message
corresponding to this request.
A server that receives a "close" connection option MUST initiate a
close of the connection (see below) after it sends the final response
to the request that contained "close". The server SHOULD send a
"close" connection option in its final response on that connection.
The server MUST NOT process any further requests received on that
connection.
So the client signals that it will close the connection by adding the Connection: close header field to the last HTTP request, and it closes the connection only after it receives the HTTP response acknowledging that the server received the request.
A server that sends a "close" connection option MUST initiate a close
of the connection (see below) after it sends the response containing
"close". The server MUST NOT process any further requests received on
that connection.
A client that receives a "close" connection option MUST cease sending
requests on that connection and close the connection after reading the
response message containing the "close"; if additional pipelined
requests had been sent on the connection, the client SHOULD NOT assume
that they will be processed by the server.
So the server signals that it will close the connection by adding the Connection: close header field to the last HTTP response, and it closes the connection. But it closes the connection only after receiving which message acknowledging that the client received the HTTP response?
If a server performs an immediate close of a TCP connection, there is
a significant risk that the client will not be able to read the last
HTTP response. If the server receives additional data from the client
on a fully closed connection, such as another request that was sent by
the client before receiving the server's response, the server's TCP
stack will send a reset packet to the client; unfortunately, the reset
packet might erase the client's unacknowledged input buffers before
they can be read and interpreted by the client's HTTP parser.
So in the case where the server initiates the close of the connection, if the server fully closes the connection right after sending the HTTP response with a Connection: close header field to an initial HTTP request, then the client may not receive that HTTP response because it received a TCP reset packet response to a subsequent HTTP request that it sent after the initial HTTP request. But how can the TCP reset packet response to the subsequent HTTP request precede the HTTP response to the initial HTTP request?
To avoid the TCP reset problem, servers typically close a connection
in stages. First, the server performs a half-close by closing only
the write side of the read/write connection. The server then
continues to read from the connection until it receives a
corresponding close by the client, or until the server is reasonably
certain that its own TCP stack has received the client's
acknowledgement of the packet(s) containing the server's last
response. Finally, the server fully closes the connection.
So in the case where the server initiates the close of the connection, the server only closes the write side of the connection right after sending the HTTP response with a Connection: close header field to an initial HTTP request, and it closes the read side of the connection only after receiving a subsequent corresponding HTTP request with a Connection: close header field or after waiting for a period long enough to assume that it received a TCP message acknowledging that the client received the HTTP response. But why would the client send a subsequent corresponding HTTP request with a Connection: close header field after receiving the HTTP response with a Connection: close header field, whereas paragraph 5 states: ‘A client that receives a "close" connection option MUST cease sending requests on that connection’?
It is unknown whether the reset problem is exclusive to TCP or might
also be found in other transport connection protocols.
But why would the client send a subsequent corresponding HTTP request with a Connection: close header field after receiving the HTTP response with a Connection: close header field, whereas paragraph 5 states: ‘A client that receives a "close" connection option MUST cease sending requests on that connection’?
With HTTP pipelining the client can send new requests even though the response for a previous request (and thus the Connection: close in this response) was not yet received. This is a slight optimization from only sending the next request after the response for the previous one was received, but it comes with the risk that this new request will not be processed by the server.
But how can the TCP reset packet response to the subsequent HTTP request precede the HTTP response to the initial HTTP request?
While the TCP RST will be send after the response it will be propagated early to the application. A TCP RST is sent if new data arrive at a socket which is already shut down for at least reading (i.e. close(fd) or shutdown(fd, SHUT_RD)). It will also be sent if there are still unprocessed data in the receive buffer of the socket on shutdown, i.e. like in the case of HTTP pipelining. Once a TCP RST is received by the peer, its socket will be marked as broken. On the next system call with this socket (i.e. typically a read or write) this error then will be delivered to the application—no matter if there would be still unread data in the receive buffer of the socket. These unread data are thus lost.
But it closes the connection only after receiving which message acknowledging that the client received the HTTP response?
It is not waiting for some application message from the client. It will first deliver the response with the Connection: close, then read on the socket in order to determine the close of the connection by the client. Then it will also close the connection. This waiting for close should of course be done with a short timeout, because disrupted connections might cause connections to never be explicitly closed. Alternatively it could just wait some seconds and hope that the client got and processed the response in the mean time.

Discard response on EAGAIN

I have a client application that repeatedly sends commands over a socket connection to a server and receives corresponding responses. This socket connection has a send/recv timeout set.
If the server is slow to respond for some reason, the client receives EAGAIN. On a timeout, I want the client to ignore that response and proceed with sending the next request.
However, currently when I ignore EAGAIN and send the next request, I receive the response from a previous request.
What is the best way to ignore/discard the response on an EAGAIN?
You can't. You have to read it. There is no mechanism to ignore bytes in a TCP byte stream.
EAGAIN may indicate a timeout elapsed (you also need to handle EWOULDBLOCK as well). If you are using TCP, you must read pending data before you can read any subsequent data. If you get an EAGAIN on a read, you have to perform the same read again, using the same parameters. Just because the server is slow to respond (or the network is slow to deliver the response) does not mean the response will not arrive at all, unless the connection is closed/lost.
If you really want to be able to receive responses out of order, you need to design your communication protocol to support that in the first place. Give each request a unique ID that is echoed in its response. Send the request but do not wait for the response to arrive. That will allow the client to have multiple requests in flight at a time, and allow the server to send back responses in any order. The client will have to read each response as it arrives (which means you have to do the reading asynchronously, typically using a separate thread or some other parallel signaling mechanism) and match up each response's ID to its original request so you know how to then process it.

HttpWebRequest/StreamWriter fails every 50th request

I'm having a problem with a .NET client connecting to an apache server for XML requests. Exactly every 50th time XML is transferred the response seems to be lost.
Looking at a WireShark trace on the client I can see that every 50th time the apache server sends an encrypted alert followed by a FIN, ACK. The client responds with a RST which closes the socket, but then the client continues to try to use the socket, it sends SYN packets without any response. When this happens the response doesn't get back to the application layer on the client.
After the client times out and reconnects (renegotiates encryption) it works another 49 times and then fails again.
Just to add this same .NET client is in use on many other client machines without a problem.
I can't find anyone else having this issue. Any ideas how to resolve this?

system call ("send") on iPhone Socket

I'm testing my iPhone application for the reaction after the Network Connection is gone.
I'm using "send" system call to send the packets over the TCP connection:
ssize_t databytes = send(sockfd, buff, readed, 0);
The problem is that after the network is gone, my server stop receiving the packets and this system call keep returning that "could send" X amount of bytes for at least 2 minutes.
How can I fix this situation? I want to be sure that the packets arrived to the server.
Best!
Usually when you send information over a network you have to receive confirmation packets. You should do the same. From the server send back to the client the amount of data received and stop sending other data until you have the confirmation.

Reason for not properly closed socket?

Here is what I am trying to do:
The server sends message to connected clients when new messages are available. The client, on the other hand, when connected, tries to send a message to the server using send() and then receive message using recv(), right after that, the client calls close() to close the connection.
Sometimes, after the client finishes, the server tries to receive message from client will result in a 104 - "connection reset by peer" error. When this happens, Wireshark reveals that the last two segments sent by the client is:
1. an ACK acknowledging the receipt of the message sent by the server
2. a RST/ACK
No FIN is sent by the client.
Why is this happening and how can I close the socket "properly" at the client?
This will occur if you call close() in the client with data still in the receive queue. The client will send RST instead of FIN, as an indication that not all data was successfully delivered to the application. If the connection was only for the benefit of the client then probably the server does not care; since no further communication is possible on that socket the server should simply close it.
This can be avoided by shutting down the connection as follows (where A is the side initiating the shutdown):
When A is finished sending all data, it calls shutdown(sock, SHUT_WR) and continues to read from socket.
When B sees EOF (e.g. recv() returns 0), it knows A is initiating a shutdown. B sends any final responses or other final data as applicable, calls shutdown(sock, SHUT_WR), and then close(sock).
When A sees EOF, if it has already shut down writes it just calls close(sock).
Note that ECONNRESET is still possible, if for example the other process is killed, so it must still be handled. In this case there is no point in sending any final response since the other side will not receive it, so the socket should just be closed in that case.