Thread: FD_READ occasional data going missing..

  1. #1
    Registered User
    Join Date
    Apr 2004
    Posts
    21

    FD_READ occasional data going missing..

    Hello all,

    Maybe someone can shed some light on this problem for me as ive ran out of ideas here. I have a client/server style game and dont have any probs on the server side but the client side is giving me a little trouble of late...

    The clients are Windows and im using Asyncronous Sockets to handle my data in coming in. When I get an Async notification I use a switch to determine the notification type.. its the read im having problems with :

    Code:
    case FD_READ:
      the_buf[0] = '\0';
      bytes_in = recv(s, the_buf, sizeof(the_buf), 0);
      if (bytes_in == 0)
      {
        MessageBox(DialogWindow, "Connection Closed","ERROR", MB_OK);
        break;
      }
      if (bytes_in == WSAEWOULDBLOCK) 
      {
        Sleep(750);
        bytes_in= recv(s, the_buf, sizeof(the_buf), 0); 
      }
      the_buf[bytes_in] = '\0';
      process(DialogWindow, the_buf, bytes_in);
    break;
    Ok now the odd thing is that this has worked fine for quite a while but someone from America connected to the server the other night (Server is in UK) and would on rare occasions "miss" bits of data being sent to them.

    For example if there were 3 of us connecting we may get the messages :

    Blah enters the room.
    Blah does something.
    Blah leaves the room.

    Note those are 3 different messages sent by the server, however on this one occasions the person in america didnt get the message "Blah does something", it just didnt display. My suspicion was that the data came through too fast and therefore couldnt be handled quick enough so I added in the check for a WSAEWOULDBLOCK, if it would block I would wait 750ms and then try again.

    This still however didnt cure the problem, doing quite abit of testing with this person it was very intermitant and didnt occur everytime and was in fact quite rare but it could be a major problem for me if the client needs to know something and its not being processed.

    Sorry for the ramble but I wanted to make the setup clear before I asked for suggestions. Is my checking for WSAEWOULDBLOCK not sufficient enough to determine if the socket is OK for reading ?

    Im also confusing myself alot at the operating system level.. When the data leaves the server by a send() function is it then held in a queue by the operating system which tries to send the client or if the send function cannot get the packet out would it simply discard it ? In terms of incoming, does the data come into an internal windows buffer of some kind which then sends my program the read notification ?

    Apologies for the rather long post but if someone could clear this up for me or point me in the right direction id appreciate it.

    Thanks

    Stan

  2. #2
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Well your error checking is actually incorrect. Give this a try:

    Code:
    case FD_READ:
      the_buf[0] = '\0';
      bytes_in = recv(s, the_buf, sizeof(the_buf), 0);
      if (bytes_in == 0)
      {
        MessageBox(DialogWindow, "Connection Closed","ERROR", MB_OK);
        break;
      }
      else if(bytes_in == SOCKET_ERROR)
      {
        int errorcode = GetLastError();
        if (errorcode == WSAEWOULDBLOCK) 
        {
          Sleep(750);
          bytes_in= recv(s, the_buf, sizeof(the_buf), 0); 
        }
      }
      else
      {
        the_buf[bytes_in] = '\0';
        process(DialogWindow, the_buf, bytes_in);
      }
    break;

  3. #3
    Registered User
    Join Date
    Apr 2004
    Posts
    21
    Thanks bithub, Ive adjusted my code to use the error checking correctly. Hopefully this will cure the problem.

    Much appreciated.

    Stan

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > the_buf[0] = '\0';
    This is pointless

    > bytes_in = recv(s, the_buf, sizeof(the_buf), 0);
    1. the_buf had better be an array (not a pointer), otherwise the sizeof will be not what you expect
    2. you don't allow room to append a \0
    bytes_in = recv(s, the_buf, sizeof(the_buf)-1, 0);

    As your code stands, a full buffer will append the zero outside the array.


    > Sleep(750);
    No guarantee that waiting this long (or any other value) will result in a message being received.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    "As your code stands, a full buffer will append the zero outside the array."

    That is wrong. recv() doesnt append a null terminator to the buffer! If it did, that would make receiving binary data rather cumbersome. The way he has it is correct.

    Code:
    char buff[128];
    recv(s,buff,sizeof(buff),0);

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > That is wrong.
    I know recv() doesn't append a \0, the code which follows does that

    char buff[5];
    n = recv(s,buff, sizeof buff, 0 );
    // if n == 5 here, then
    buff[n] = '\0';
    is a buffer overflow!
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Yes, you are correct. I misunderstood what you meant in your earlier post.

  8. #8
    Registered User
    Join Date
    Apr 2004
    Posts
    21
    Hi,

    Thanks for the suggestions. Salem you mentioned in your post that :

    No guarantee that waiting this long (or any other value) will result in a message being received.

    You are correct as after doing some more testing ive started missing packets again on the clients when there is alot of activity on the server and its trying to send out data to the clients pretty fast.

    Im stuck in identiying if the problems are with my sloppy network code on the client or on the server or if my network implementation is not working correctly. Ive even considered putting incoming messages into a queue system and actioning them each cycle rather than as and when they come in.

    I know this is a very generalised question but has anyone any suggestions or procedures of what I could look into to figure out the best way to deal with fast incoming data? Any hints or tips regarding getting all the data in and trying to avoid the packet loss would be most appreciated.

    Thanks

    Stan

  9. #9
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    One option is to use regular blocking sockets in a different thread. Then you can use windows messages or some other mechanism to notify your main thread when data comes in. This removes the whole problem of having to worry about WSAEWOULDBLOCK.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Or just use select with a timeout to determine if there is anything to be read, then save yourself a whole bunch of complications which result from trying to synchronise threads.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Lame null append cause buffer to crash
    By cmoo in forum C Programming
    Replies: 8
    Last Post: 12-29-2008, 03:27 AM
  2. Program Crashing
    By Pressure in forum C Programming
    Replies: 3
    Last Post: 04-18-2005, 10:28 PM
  3. Binary Tree, couple questions
    By scoobasean in forum C Programming
    Replies: 3
    Last Post: 03-12-2005, 09:09 PM
  4. Data missing in variable
    By nizbit in forum C Programming
    Replies: 8
    Last Post: 03-07-2005, 08:22 AM
  5. odd errors from msvc std library files
    By blight2c in forum C++ Programming
    Replies: 6
    Last Post: 04-30-2002, 12:06 AM