locked
GetOverlappedResult() or ReadFile() on Socket returns TRUE with lesser number of bytes RRS feed

  • Question

  • Hi,

     

    I am writing a TCP/IP Server application that handles several clients.

    I am using the overlapped ReadFile() and WriteFile() in a single thread per client inside the Server. Every client sends data to Server in packets of size 2 kbytes each.

    Server if required, sends data to a client in packets of size 2 kbytes each.

    In general, this is working fine.

     

    After calling ReadFile() which returns error code ERROR_IO_PENDING, I am using a WaitForSingleObject with Timeout for the Overlapped Read completion event.
    When Overlapped event is signalled, I check the result as below:
    GetOverlappedResult( ClientSocketHandle, &ovReadStruct, &dwBytesRead,  FALSE);


    With 20-100 ms timeout for WaitForSingleObject, I did not find any problems.
    However, with 0 ms timeout, I face the following problem occasionally for a client. After few hours, it may happen for another client:

     

    ReadFile() or GetOverlappedResult() returns TRUE with lesser number of bytes than requested.

    ReadFile() is requested for 2048 bytes.
    Very rarely, the Bytes read is 1460 bytes.
    But, return value is TRUE!!!


    Can someone explain why and how this can happen?
    Is this a known behaviour of overlapped ReadFile with Sockets?

    If so, how to handle this?
    For overlapped operation for Serial Port, I have read in MSDN that the overlapped operation can get timed out, and hence return fewer number of bytes read till then.
    But, nothing is documented about the behaviour on Sockets.


    I will be thankful if some one can help me out!

    Tuesday, May 15, 2007 1:09 PM

Answers

  • There is no such guarantee with ReadFile (or any other Winsock receive function) to wait until the buffer is completely full. It can return at any point with 1-n bytes of data. A send request will always wait until all the requested bytes have been sent.

     

    If  you are on Windows Server 2003+ you can use WSARecv with the MSG_WAITALL flag which will wait until the entire buffer is filled (which could take forever if the peer is not sending the expected number of bytes).

     

    -Anthony Jones (MSFT)

    Tuesday, May 15, 2007 11:09 PM

All replies

  • This is the Peer-to-Peer Networking Development forum.  The win32.prgrammer.networks newsgroup is probably a better place to post this question (and a quick search indicates you haven't yet posted there).

     

    GetOverlappedResult() returns TRUE because the read succeeded.  It just happened to be for less data than you asked for.  The MSDN docs are vague about whether or not this should be happening in the case of a socket but I think you've got evidence it can happen.  What action are you trying to decide to take?  I expect you will have to write code to deal with GetOverlappedResult() returning TRUE and yielding fewer bytes than you requested in order to have a robust Server application no matter what the documented behavior is (unless you were hoping for a bug fix I suppose).

     

    Please direct further questions about behavior of overlapped ReadFile() using sockets to win32.programmer.networks.

    Tuesday, May 15, 2007 9:36 PM
  • There is no such guarantee with ReadFile (or any other Winsock receive function) to wait until the buffer is completely full. It can return at any point with 1-n bytes of data. A send request will always wait until all the requested bytes have been sent.

     

    If  you are on Windows Server 2003+ you can use WSARecv with the MSG_WAITALL flag which will wait until the entire buffer is filled (which could take forever if the peer is not sending the expected number of bytes).

     

    -Anthony Jones (MSFT)

    Tuesday, May 15, 2007 11:09 PM
  •  

     

    Thanks for the reply.

    Sorry, it was my mistake to post at the wrong forum.

    I will direct further posts on this topic to win32.programmer.networks.

    Wednesday, May 16, 2007 7:56 AM
  •  

    In this case, the sender (client) had sent all the data bytes, but the receiver (Server) side ReadFile did not read all bytes.

     

    Wednesday, May 16, 2007 7:58 AM
  • Even though ReadFile returns TRUE, it does not necessarily mean a complete read; it only indicates a successfull operation. You need to place the read opearation in a loop, calling GetLastError() on each iteration. If GetLastError() returns ERROR_IO_PENDING, continue reading. At the end of the read, number of bytes read would be 0.

    Sunday, June 10, 2007 2:36 AM