Question

I am working on UDP server and this code of UDP server is working fine except the else condition. May be i am wrong but i have done lot of things using else condition in the same way to terminate while loop. I am not sure if its UDP problem or something else........

while(1)// execute three times because its getting data only three times from the client
    {
    int total_bytes = 0;
    int bytes_recv=0;
    int count = 0;
    std::vector<double> m_vector(8000);

        // Bytes are also received 3 times correctly then why else condition not executing after receiving 3 times ?
         bytes_recv = recvfrom(Socket,(char*)m_vector.data(),64000,0,(SOCKADDR*)&ClientAddr,&i);
        count++;

        if(bytes_recv > 0 )
        {
            total_bytes = total_bytes+bytes_recv;
            std::cout<<"Server: loop counter is"<<count<<std::endl;
            std::cout<<"Server: Received bytes are"<<total_bytes<<std::endl;
        }else

        {
        //why this part  never executes ? 
            std::cout<<"Data Receiving has finished"<<std::endl;
            break;
        }
    }

    WSACleanup();
    system("pause");
    return 0;
    }

No correct solution

OTHER TIPS

The comment in the source says that you expect only 3 datagrams from the client. Thus, do count how many datagrams you have received, and if you already have 3 of them, do not continue calling recvfrom.
You already have a variable count, but it is reset to zero every iteration and isn't used as exit condition.

Once you have count == 3, you know that there is nothing more coming, so calling recvfrom is pointless. It will only block, since that is what you're telling it to do. Making the socket non-blocking would "help" to avoid blocking, but then you would be polling, which isn't good either (and useless, since you know there is nothing to be received). It's best to operate correctly.

You could also have the client send an "end of message" datagram, but of course you would have to add a timeout and a strategy for packet loss, or the server could block forever. Not only because of malicious clients, but also simply because the receive buffer was full and a packet was dropped (which is a normal thing to happen!).

Alternatively, since there is a call to WSACleanup in your code, you're using Winsock. Which means you could use overlapped WSARecvFrom instead of recvfrom. Fire off one receive, and from its completion handler fire off another two, also with a callback function. After firing off the request, forget about it and let the callback handle the rest, you can now deal with another client (must be alertable though for that to happen ... alternatively, block on an IOCP or WaitOnMultipleObjects or whatever).
If no second or third packet comes in after so and so long, either send a "please resend" message or consider the client dead, close the socket and move on.

recvfrom is by default a blocking call and will only return once a packet has been read. Because of this when you stop sending packets it just blocks on recvfrom so the case with 0 bytes never happens

You could change the flags to recvfrom to change this behaviour, but it's likely not what you want because then if there's any delay between sending the packets you will get 0 bytes and exit.

I suppose you could see how long you've gone without receiving any packets and then shut down, so in the else case you could use a timer and a running total before exiting.

What are you trying to accomplish?

I have not checked (bad me, I know, but time's short), if recvfrom follows typical behavior, then it guarantees you that:

  • returns value < 0 means error
  • returns value == 0 means that everything was OK but channel cannot receive anything more
  • returns value > 0 means something was received

In TCP you get 'received bytes' == 0 only when the connection is closed.

In UDP there's no such thing as 'connection'. The channel is always ready to receive, until your the socked is closed.

Hence, it probably simply waits until something arrives. It cannot detect that there is noone to listen from. That's the UDP specifics.

If you want to catch a case when nothing arrives for a long time, try to set read timeout.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top