Partial Write for sockets in LINUX

We have a server-client communication in our application. Sockets are used for the communication. We are using AF_INET sockets with SOCK_STREAM(TCP/IP). Also these sockets are in Non Blocking mode (O_NONBLOCK). Application is written in C++ on UNIX.

In our system the Server will write to a socket and Client will read from it. We had written code to handle partial writes. If a partial happens, we will try 30 more times to write the entire data.

Our Server try to write 2464 bytes to the socket. In some cases it could not write entire data. So server will try writing 30 more times to transfer entire data. Most of the times the entire data will be written within 30 tries. But some times the even after 30 reties sever wil not be able to write the entire data. Here it will throw EAGAIN error. Problem happens in the Client Side when it tries to read this partially written data.

Consider the server tried to write 2464 bytes. But after the repeated 30 attempts it could write only 1080 bytes. Server will raise a EAGAIN at this point. Client try to read 2464 bytes. The read command will return 2464 and hence the read itself is ok. But the data we received is a corrupted one (Partially written data only). So client crashes.

Can any one please advise on following,

1) Is it possible to remove only the partially written data by the server itself. Thus the client will not recieve corrupted incomplete data?. (We cannot use a read() function from server to remove this. Consider server successfully written n messages to the socket. Client is in busy state and not able to read them. Then the server try to write the n+1 th message and Partial write occured. If we use read command from the server, the entire n successfull messages alo get removed. We need to remove the Partially witten (n+1 th) message only)

2) Is there any way to identify in client side that we had read a partially written message?.

Please note that we are facing the partial write issue in LINUX(REDHAT 5.4) only. System is working fine in Solaris (In solaris either eh entire data will be written OR NO data witll be written with in 30 tries of write).

Thanks in advance.

Any reason for not using standard blocking mode?

I can't quite follow. If only 1080 has been sent, I don't think that read() returns 2464 bytes...

You need to handle partial read anyway with TCP, since you don't know how your message will be segmented. The usual design pattern goes along those lines:

  • a message is composed of a header and payload section,
  • the header contains (among other) the payload size,
  • the receiver read() first the header (a few bytes), decodes the expected payload length. To get the payload, it re-iterates read() until the wanted size is reached or an error occurs.

Perhaps tune kernel parameters TCP send/recv queue length ?

HTH, Lo�c

You're probably spinning your write() retries faster than the buffers that feed the socket can drain. If it's not returning an error, keep trying to send the bytes that you didn't already send.

And FWIW, the number of bytes a read() returns on the other end are only loosely correlated with what you write(). The data comes out as a stream - literally. If you have to take it apart, you have to provide your own delimiters as Loic already posted.

Just because it works fine under Solaris and not under Linux means almost nothing.

Thank you all very much for your answers. The real problem is i cannot perform the write infinitely/BLOCKING mode, since there are lot of other clients waiting the response from server. Let me try some code changes with inputs from your answers.

Consider going multi-threaded (or multi-forked)... This may simplify greatly your concurrency concerns.

Cheers, Lo�c