#1
  1. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Location
    Canada
    Posts
    2
    Rep Power
    0

    Winsock cant recv() any data


    I can't recv() any data on a non-blocking socket.

    Basicaly the conection is accepted, thats for sure, useing telnet I conect. Then I start to type, but my server cant recv() it returns 0

    case FD_READ:
    {
    int iRet;
    char buffer[25];

    iRet = recv(client, buffer, 25, 0);

    if (iRet == 0)
    MessageBox(NULL, "Conection closed?", "Debug", MB_OK);

    send(client, "Test", 4, 0);

    break;
    }
    always returning 0, can someone help me?
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2002
    Location
    BCN
    Posts
    84
    Rep Power
    13
    Hi,

    Recv = 0 means that the sender has closed the connection. Check it. If there was some other kind of error you 'd get -1.
  4. #3
  5. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243

    The key is 'non-blocking'


    Depending on your underlying socket implementation, sometimes the return value is largely meaningless and you need to call another routine to get details on the 'error'. Certainly if you are using non-blocking sockets, you should expect your recv() to return immediately almost all the time, and since the normal return value is the number of bytes retrieved, you should expect zero to show up quite often. You would need to put it in a loop and constantly test it (I strongly suggest against that! Simply use normal 'blocking' sockets). There are not many needs for non-blocking sockets, I would suggest you review your requirements and see if there is a way around it. Try googling on 'non blocking' and 'recv' to get more information.

    Mitakeet

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,086
    Rep Power
    2222
    As Mitakeet points out, the key is that you are using non-blocking sockets, which require some extra special handling that you are not doing.

    With non-blocking sockets in Winsock, recv should return a value of SOCKET_ERROR and a call to WSAGetLastError() return a value of WSAEWOULDBLOCK if a blocking socket would have blocked -- i.e. if there was no data immediately available to be read.

    Here is the Visual C++ help page entry on WSAEWOULDBLOCK:
    WSAEWOULDBLOCK
    (10035)
    Resource temporarily unavailable.
    This error is returned from operations on non-blocking sockets that cannot be completed immediately, for example recv when no data is queued to be read from the socket. It is a non-fatal error, and the operation should be retried later. It is normal for WSAEWOULDBLOCK to be reported as the result from calling connect on a non-blocking SOCK_STREAM socket, since some time must elapse for the connection to be established.
    The idea with non-blocking sockets is that there are other things that you want to be doing or checking in the meantime. In the meantime, instead of being extremely busy in a tight loop, you could add a Sleep() for a number of milliseconds.
  8. #5
  9. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2003
    Location
    Canada
    Posts
    2
    Rep Power
    0

    loop tells me data awaits me but no.


    non-blocking is the best solution for my case, as my searching google indicates. And as you said, non-blocking is for when you have other things to do in the mean time while you are waiting for data. This is my case as I have a GUI to process.

    I used WSAAsyncSelect, this tells Windows to send a FD_READ message to my window handler when data is ready for me. The loop taken care of for me by Windows.

    Indeed every time i push a key in telnet, my FD_READ is being called, I can put a messagebox in there.

    Im not sure why my conection is being closed. Telnet is ceritanly not telling me its closed. The return is not equal to SOCKET_ERROR I checked, the return value is 0, indicating no conection. But this is whats weird, because I recieve a FD_ACCEPT message when I get a conection,l and this too I have verified with a message box, and I accept() the conection:



    // Global data
    WSADATA ws;
    SOCKET sock, client;
    SOCKADDR_IN addr, addr_remote;

    /* WSAAsyncSelect tells it to send my window handler a message when data is waiting and a conection is made */

    WSAStartup(MAKEWORD(1,1), &ws);
    sock = socket(AF_INET, SOCK_STREAM, 0);
    bind(sock, (LPSOCKADDR)&addr, sizeof(struct sockaddr));
    listen(sock, 100);
    WSAAsyncSelect(sock, hWindow, WM_SOCKETEVENT, FD_ACCEPT | FD_READ);

    // My handler gets called when socket activity ocures

    switch(WSAGETSELECTEVENT(lParam)){
    case FD_ACCEPT:
    {
    int clientInfo = sizeof(struct sockaddr);
    client = accept(sock, (LPSOCKADDR)&addr_remote, &clientInfo);
    }
    break;
    case FD_READ:
    {
    int iRet;
    char buffer[25];

    char *buff = readLine(client);

    if (iRet == 0)
    MessageBox(NULL, "Conection closed?", "Debug", MB_OK);
    send(client, buff, strlen(buff), 0);
    }
    break;
    }
    always getting socket closed.

    char * readLine(SOCKET s) {
    /* stuff.....
    ....*/

    bytesReceived = recv(s, &buffer, 1, 0);
    if (bytesReceived <= 0){
    // Here i had a if == 0 before, so thats how i know rev returns 0.
    return NULL;
    }
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,086
    Rep Power
    2222
    Wait a minute. If you're using select (or at least the Winsock variant of it), then why are you also using non-blocking sockets? select is already telling you that the socket is not going to block because it does have something to read.

    For that matter, feeding WSAAsyncSelect a non-blocking socket might even mess it up. Try it with a blocking socket and see what effect that has.

IMN logo majestic logo threadwatch logo seochat tools logo