Question

I'm attempting to write a simple server using C system calls that takes unknown byte streams from unknown clients and executes specific actions depending on client input. For example, the client will send a command "multiply 2 2" and the server will multiply the numbers and return the result.

In order to avoid errors where the server reads before the client has written, I have a blocking recv() call to wait for any data using MSG_PEEK. When recv detects data to be read, I move onto non-blocking recv()'s that read the stream byte by byte.

Everything works except in the corner case where the client sends no data (i.e. write(socket, "", 0); ). I was wondering how exactly I would detect that a message with no data is sent. In this case, recv() blocks forever.

Also, this post pretty much sums up my problem, but it doesn't suggest a way to detect a size 0 packet. What value will recv() return if it receives a valid TCP packet with payload sized 0

Was it helpful?

Solution

When using TCP at the send/recv level you are not privy to the packet traffic that goes into making the stream. When you send a nonzero number of bytes over a TCP stream the sequence number increases by the number of bytes. That's how both sides know where the other is in terms of successful exchange of data. Sending multiple packets with the same sequence number doesn't mean that the client did anything (such as your write(s, "", 0) example), it just means that the client wants to communicate some other piece of information (for example, an ACK of data flowing the other way). You can't directly see things like retransmits, duplicate ACKs, or other anomalies like that when operating at the stream level.

The answer you linked says much the same thing.

OTHER TIPS

Everything works except in the corner case where the client sends no data (i.e. write(socket, "", 0); ).

write(socket, "", 0) isn't even a send in the first place. It's just a local API call that does nothing on the network.

I was wondering how exactly I would detect that a message with no data is sent.

No message is sent, so there is nothing to detect.

In this case, recv() blocks forever.

I agree.

I have a blocking recv() call to wait for any data using MSG_PEEK. When recv detects data to be read, I move onto non-blocking recv()'s that read the stream byte by byte.

Instead of using recv(MSG_PEEK), you should be using select(), poll(), or epoll() to detect when data arrives, then call recv() to read it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top