0

Please, someone kindly help me how to catch socket operation's error from CAsyncSocket Class.

If I do this:

int iLen = recv(socket, socketBuffer, sizeBuffer, 0);
if(iLen==SOCKET_ERROR) {
   //handle error here
} else {
   //do something with the received data
}

It always returns error, which is WSAEWOULDBLOCK, and the same for other operation like send(), connect(), etc...
According to MSDN, it's not a fatal error, and some time must elapse for the actions to be finished.

So how can I actually check every time my program did recv() or send() correctly?

Trung Nguyen
  • 177
  • 1
  • 12
  • The last argument to [`recv`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx) is an *integer* flag value, not a pointer. So you should not use `NULL` there. – Some programmer dude May 11 '16 at 06:37
  • As for your problem, `WSAEWOULDBLOCK` is simply telling you that there is nothing to receive yet on the *non-blocking* socket. You can use [`select`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx) or [`WSAPoll`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms741669(v=vs.85).aspx) to poll if the socket(s) is having anything to read. – Some programmer dude May 11 '16 at 06:40
  • Thank you for your comment, in MFC they define NULL as 0; however, I did edit my code as your suggestion. For the select(), I still have no clue how to use it. – Trung Nguyen May 11 '16 at 07:27

1 Answers1

1

First of all you should not mix CAsyncSocket API and Berkley Socket API.

Your OnReceive handler should look like this:

    CByteArray InBuffer; 
    InBuffer.SetSize(DEFAULT_RX_BUFFER_SIZE);       
    int nBytes = Receive(InBuffer.GetData(), (int)InBuffer.GetSize());

    switch (nBytes)
    {
        case 0:
            ShutDown(CAsyncSocket::both);
            break;
        case SOCKET_ERROR:
            if (::GetLastError() != WSAEWOULDBLOCK) 
                ShutDown(CAsyncSocket::both);
            else
                AsyncSelect();
            break;
        default:
            {
                // TODO: data processing goes here
            }
            break;  
    }
Andrew Komiagin
  • 6,446
  • 1
  • 13
  • 23
  • Thank you for your comment. So I should do the same for Send(), Listen(), and Connect()? Btw, where is DEFAULT_RX_BUFFER_SIZE defined? I can't find it. – Trung Nguyen May 11 '16 at 09:25
  • Yes, there are `OnConnect`, `OnSend` and other handlers. The error handling is pretty much the same. The `DEFAULT_RX_BUFFER_SIZE` constant is user defined. – Andrew Komiagin May 11 '16 at 09:28
  • I know it is not in the question, but it is completely different than how I am expecting. How can I only get the first 4 bytes of the whole? Because, I actually packed 2 data when I sent out. The first is int, and the second is char*. When I applied your code, it pull down everything in the `default:` – Trung Nguyen May 11 '16 at 10:24
  • Not a problem. Just use first four bytes: `InBuffer[0]`, `InBuffer[1]`, `InBuffer[2]`, `InBuffer[3]` – Andrew Komiagin May 11 '16 at 10:50
  • That's interesting. Then what happen if the data I sent was much bigger than the number I define in `DEFAULT_RX_BUFFER_SIZE` ? For example if I sent a file, or an array of picture's byte which I have no idea how long it is? – Trung Nguyen May 11 '16 at 12:27
  • If you still have data left the framework will automatically call `OnReceive` after `AsyncSelect()` – Andrew Komiagin May 11 '16 at 12:52
  • Thank you, but one more question. If I still have data left, then `OnReceive` will be called multi-time. In my case, it was called 9000 times! What if I want to store received data to some where else and only do calculating with the whole data outside the loop? where should I put that function? Is it inside `case 0:`? – Trung Nguyen May 12 '16 at 02:00
  • You should process received data in a separate thread. Make sure you guard the data buffer using `CCriticalSection`. – Andrew Komiagin May 12 '16 at 06:51
  • Well, I know how to use postmessage() to the other thread in other to append the data. But how can I know when whole data is completed receiving to begin calculating? – Trung Nguyen May 12 '16 at 08:47
  • Thank you, I think I must re-plan the way to send data first. Need a better protocol, I guess... – Trung Nguyen May 12 '16 at 09:50