Discard response on EAGAIN - sockets

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.

Related

Is it possible for POST requests sent sequentially to be received out of order?

I'm a bit new to restful API usage.
suppose that I am sequentially sending out 1000 post requests in python, is it possible that my server could receive these requests out of order? (for example post request 5 is somehow received before post request 4)
If it is not possible for requests to be handled out of order, how do web application frameworks know what order to handle the requests in? is there some sort of timestamp/metadata that indicates priority of the request? For example, does the oldest request HAVE to be fulfilled as soon as possible?
I am curious because I am using the POST api to populate my database and I noticed that my sequentially sent data NEVER has come out of order. I don't want to be dependent on this assumption that sent data will always be consistently in the proper order, so I thought I should ask here
If you are sending requests and wait for a response before sending the next one, then everything will happen in order, guaranteed.
If you are sending many requests in parallel, there's generally no guarantee which will arrive first and get processed first.
It's pretty reasonable to assume that the request that arrives first also gets processed first, and over a local fast network that may usually be the case; but over the internet specific packets can get delayed for lots of reasons. Even wifi might cause one of your requests to have to be resent if it wasn't received well the first time.
tl;dr: the only way you can guarantee order is if you wait for a response before sending the next request.

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

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

Is it possible to batch multiple HTTP messages inside a one packet?

A friend of mine mentioned that I could send TLS application data (HTTP messages) in batch fashion inside a one TCP packet instead sending one by one.
I've researched his claim using Google but couldn't find any.
Is this possible? Wouldn't this cause parsing issues for browsers?
HTTP is a request-response protocol, i.e. each request expects a response. The traditional way with HTTP/1 was to first send a request, then wait for the response, then send another request (if HTTP keep-alive is supported and the connection stayed open) and expect the response etc. With this procedure it could not be possible that multiple requests end up in the same packet since one had to wait for the response of the current request before sending the next one. Similar multiple responses could usually not end up in the same packet since there was also a single response outstanding. A special case here is a preliminary response (status code 100) which is followed by the "real" response. These could be sent together.
It is possible with HTTP pipelining to send multiple requests at once and then wait for all the responses to be sent back in the same order as the requests were sent. In this case multiple requests could end up in the same packet and multiple responses too. But the server is actually allowed to close the connection after a response is done. In this case requests might be left unanswered and one might need to resent the requests. But it might actually happen that the server has processed the request but that the connection was closed before sending the response, so replaying should only be done if it does not change the semantics (i.e. idempotent requests).
HTTP/2 then supports parallel sending of requests, i.e. requests can actually be interleaved in each others and same with responses. This way also multiple requests or responses might end up in the same packet.
Apart from that a clarification might be needed: a normal application does not send TCP packets but it sends data. How these data are packetized for transport is up to the kernel and depend for example on MTU. It might be that a single send results in multiple packets. It might also be that multiple send shortly after each other are combined together into a single packet.

UDP response received after timeout

We have an UDP client that communicates against a server.
The server gives a single response on each request.
The client sends a request, and waits 5 seconds for the response.
If the server's response was not received by 5 seconds - the client assumes that the packet was lost in the network (this is UDP...), writes a report to a log, and sends the next request.
But, sometimes we have any delay in the network, and the server's response comes after 5 seconds.
Let's describe the scenario:
The client sent a packet named "X".
The timeout of 5 seconds expired, and the client reports that "X" is a lost packet.
The client sent another packet named "Y".
The server's response on "X" comes now to the client.
The client sees that the response is not compatible to the request, and report it to the log.
The client sent another packet named "Z".
The server's response on "Y" comes now to the client.
The client sees that the response is not compatible to the request, and report it to the log.
And this is an infinity loop!
What can we do?
Many UDP-based protocols include an identifier to indicate which request a given response belongs to. The client chooses the identifier and sends it to the server as part of the request, and then the server echoes it back in the response. This allows the client to match responses to requests, especially in situations like the one you describe. If the client received the response to X after having moved on, it would be able to simply ignore that response.

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.