0

I'm writing a simple http server for a test and I'm rather confused as to how one is supposed to tell where the end of a request is.

recv() returns a negative number on error, 0 on connection close and a positive number receiving data, when there is no more data it just blocks.

I could create some frankenstein that continuously recv's on one thread and checks if it blocked on another thread but there has got to be a better way to do this... How can I tell if there is no more bytes to read for the time being without blocking?

user81993
  • 6,167
  • 6
  • 32
  • 64
  • TCP is a stream of bits. It knows nothing about whatever protocol you push through that stream, so you are forced to read data and search for the beginning and end of your protocol's messages. Since you don't want to sit blocked, you may find non blocking sockets useful. Also worth looking into Overlapped IO. Hers's some decent documentation to get you started: https://learn.microsoft.com/en-us/windows/win32/winsock/socket-i-o-2 – user4581301 Jun 25 '21 at 20:48
  • 3
    You should follow the HTTP since you are writing a HTTP server. The end of header is represented by `\r\n\r\n"`. The `Content-Length` header is useful to find the end of request body. – MikeCAT Jun 25 '21 at 20:51
  • "*I'm rather confused as to how one is supposed to tell where the end of a request is ... How can I tell if there is no more bytes to read for the time being without blocking?*" - by reading the [HTTP spec](https://tools.ietf.org/html/rfc2616) and following the rules and formats it defines. I've covered this a number of times before (on the client side, but it applies on the server side, too): https://stackoverflow.com/a/16247097/65863, https://stackoverflow.com/a/30472253/65863, https://stackoverflow.com/a/7234357/65863, https://stackoverflow.com/a/14421507/65863 – Remy Lebeau Jun 25 '21 at 22:21
  • @MikeCAT Thanks for the hint. From what I understand, the request content could still be malformed though? What if the end sequence never comes, I'd stumble into another recv and be locked down on that thread until the connection interrupts? – user81993 Jun 26 '21 at 00:59

1 Answers1

0

First of all, you should follow the HTTP protocol when reading the HTTP request:

  1. Continue reading from socket until \r\n\r\n is received
  2. Parse the header
  3. If Content-Length is specified, additionally read that many bytes of the request payload
  4. Process the HTTP request
  5. Send HTTP response
  6. Close the socket (HTTP/1.0) or (HTTP/1.1) handle keep-alive, content-encoding, transfer-encoding, trailers, etc, potentially repeating from step 1.

To deal with potentially misbehaving clients, when using blocking sockets it is customary to set a socket timeout prior to issuing recv or send calls.

DWORD recvTimeoutMs = 20000;
setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&recvTimeoutMs, sizeof(recvTimeoutMs));
DWORD sendTimeoutMs = 30000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&sendTimeoutMs, sizeof(sendTimeoutMs));

When a recv or send times out, it will fail with WSAGetLastError giving WSAETIMEDOUT (10060).

rustyx
  • 80,671
  • 25
  • 200
  • 267