views:

49

answers:

4

I've been reading the man page for read(2) and according to the man page, the return value of read(2) is -1 on error, 0 on EOF, and > 0 for the number of bytes read.

How do I tell when the write(2) on the client is finished ?

I ask because I'm writing a server and a client to test it, but when I read(2) the first time and loop around to check for more, read(2) blocks and waits for another write(2) from the client (which isn't coming because my client only has the one write(2)).

If I'm just missing something simple, could somebody kindly point it out or point me to a good reference ?

+3  A: 

The client needs to close the socket when it's done. Once the client has closed the socket, the server will received the EOF message. If the client leaves the socket open but never writes to it, the server will wait forever for another message to come down.

JSBangs
What about when the client and server have multiple reads / writes ? Do I have to start using headers as noah suggests ?
Alex Marshall
You really shouldn't close the socket just to receive one message. I think Justin's answer is the correct way.
ChaosPandion
@Chaos, I understood the OP to only *want* to send/receive one message. @Alex, if you want to receive multiple messages, then you can use signaling as Noah suggested, prepend a header with the number of bytes in the current message, or use a message-oriented protocol.
JSBangs
+1  A: 

You know you are done when read returns:

  • -1 - An error occurred
  • 0 - EOF
  • Another, non-zero value - This is the most common case. You protocol needs to specify the size of its messages using either a header specifying message size or fixed-length messages. Then you can keep track of the number of bytes read, and you know you are done once you have read that many bytes. Otherwise you need to keep reading bytes until you have received a full message.
Justin Ethier
All of this was stated in the question.
noah
@noah - did you read the last item in the list?
ChaosPandion
@Chaos - Exactly. @noah - The first two were mentioned, but the last (and most important!) bullet was not. The point is that you need another strategy for reading multiple messages from a socket. In addition to the methods I describe, you could also use a delimeter as you suggest, with some caveats.
Justin Ethier
A: 

There is no correspondence between reads and writes. A single client write might take you 10 reads to fully load. Unless you put a delimiter in the content, you have no way of knowing where the end is, unless the socket is closed.

If you still need to send a response to the client, you can half close the socket on the client:

shutdown(socket, SHUT_WR);

Which will cause the read on the server to return 0.

noah
What kind of delimeter do you suggest? How do you know that the delimeter will not also appear in the message data?
Justin Ethier
I think he means something like a null character. (if you are sending text.)
ChaosPandion
You can use whatever delimiter you want as long as the client escapes it if it occurs in the data normally. But unless there is a need for the connection to stay open, (half) closing the socket is the better option.
noah
A: 

Something to look at would be to use the select() first to check for data, and specify a suitable time out period, rather than just blindly calling read(). This will allow your server to close the socket after a set period of inactivity, and free any resources it might be use, etc.

Gareth Wilson