Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

socket recv() - End Of Stream ?

Status
Not open for further replies.

sedj

Programmer
Aug 6, 2002
5,610
Hi,

I have a recv() call on a socket :

Code:
while ((iRecvSize = recv(iSocketDesc, szRequestBuffer, REQUEST_SIZE-1, 0)) > 0) {
  // extract data
}

Currently I am looking for a specific "end of data/stream character" - ie a tilde on the end of the data string, which if I see, then I break from the recv loop.

There must be some better way of doing this, but I can't figure out how.
I was expecting that the recv() call would return 0 or -1 at the end of the stream/data, but it never does. So if I don't send the "end of stream character", then recv() call just locks because the client thinks its sent all the data, but the server is still looking for more.

is this defined behaviour does recv() not return -1 or 0 or something when there is no more data ?

(Using linux, GCC 3.2)

Thanks ofr any help.
 
Yes, recv() and send() are blocking functions meaning that if there is no data available then it will block the process until more data becomes available. For what you are wanting to do you need to use the optional "flag" argument (you have a 0 in it at above). Put in MSG_DONTWAIT instead of 0 and then the recv call will NOT block if ther eis no data, but instead will return with a -1 and errno set to EAGAIN if it WOULD have blocked. Basically you can just run a check that if it returns -1 and errno==EAGAIN then everything is ok.

Code:
while ((iRecvSize = recv(iSocketDesc, szRequestBuffer, REQUEST_SIZE-1, MSG_DONTWAIT)) > 0) {
// extract data
}

if( (iRecvSize==-1) && (errno!=EAGAIN) )
{
//a non-standard error occured and needs to be handled
}
 
Thanks for the reply rburke.

When I added the MSG_DONTWAIT call, it does indeed not block the recv() call, but also fails to actually read any of the packets (there are say, 5 packets/calls to recv normally).

I'm a bit lost here really - I've started to play around with different flags etc, but nothing seems to work.

Just to recap, a client will send (say) 5 packets to the server, so the server loops for 5 times around recv(), building a char* of the request. This is OK as long as I break on a end-of-stream character, but if this char is never sent (dodgy packet, bad client etc), the server recv() blocks.
Using MSG_DONTWAIT however never recv()'s any actual data, and breaks (returns -1 with EAGAIN indicating that it would have blocked) on the first call.


I am using the following parameterswhen actually creating the server's socket :

Code:
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)

Any ideas whats going on ?
 
Think about TCP/IP stream socket logics. No any special protocol-defined end-of-stream bytes. The only end-of-connection condition araised when the peer closed connection. In that case your recv() returned normally with 0 bytes read.

So you must define any application-level protocol (or use any common protocol - HTTP, for example) to decide if all data received. Remember: there is another side of a socket stream and you don't know what it does now and in the next (milli)second...

Really your application may use multi-threaded approach (start receiver thread and synchronize it with the main thread), or use time-out approach (try-wait-retry-close).
 
Thanks ArkM,

Stupidly, I was using MT to handle the "char* request", but was not actually MT'ing the recv() off the client socket.

I have now done this, and added a time-out so if some data is bad and it locks up, the whole server does not lock.

Why I didn't do that earlier I have no idea ?!!!



--------------------------------------------------
Free Database Connection Pooling Software
 
Sorry, of course it won't work since the -1 will break out of the loop. Below would be an example:

Code:
int iRecvSize = 0;
int cont_flag = 0;
int tilde_flag = 0;

do
{
  if( (iRecvSize = recv(iSocketDesc, szRequestBuffer, REQUEST_SIZE-1, MSG_DONTWAIT)) < 0)
  {

    switch(errno)
    {
      case EAGAIN: 
                   {
                     break;
                   }
      default:
               {
                 perror("Critical error occured in recv()");
                 cont_flag = 0;
                 break;
               }

    }
  }
  else
  {
    //process the data and look for ~, set found_tilde when found
    if( found_tilde )
    {
      cont_flag = 0;
    }
  }

} while (cont_flag == 1);

That may not be syntatically correct, but logically should work for you.

Burke
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top