LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   fgets on socket (https://www.linuxquestions.org/questions/programming-9/fgets-on-socket-553370/)

nc3b 05-12-2007 09:43 AM

fgets on socket
 
I have written a simple server ( which uses select() ) and until now I have tested it with telnet. Now I started to write a simple client, but came across a problem.

Because my client (like the server) needs to respond immediately, I can't risk letting it to block. So, I decided to multiplex STDIN_FILENO and the socket I use in the client with select. It's all just like in the server, just that there I multiplex more sockets. So, I use this code. sock is the socket, rx is the fd_set

PHP Code:

//.....
rx=fdopen(sock,"r");
for(;;)
{
    
select_status=select(sock+1,&rx_set,NULL,NULL,&tv);
    if(
select_status==-1)
    {
        
cout<<"out\n";
        return(
1);
    }
    else
    {
        if(!
select_status)
        {
            
cout<<"timeout\n";
            continue;
        }
    }
/*    if(FD_ISSET(STDIN_FILENO,&rx_set))
    {
        fgets(m_buf,sizeof(m_buf),stdin);
        fputs(m_buf,tx);
        fflush(tx);
    }*/

    
if(FD_ISSET(sock,&rx_set))
    {
        
fgets(buffer,sizeof(buffer),rx);
        if(
feof(rx))
        {
            return(
1);
        }
        
cout<<buffer<<endl;
    } 

I commented out the first FD_ISSET because it was blocking. Now, I have a problem. Sure enough, the server is sending a string as greeting to the client, yet the client prints nothing, AND it blocks on fgets. Please help. Thank you.

wjevans_7d1@yahoo.co 05-13-2007 08:36 PM

If the server is not sending a line feed at the end of its message, chances are you will block, because fgets() won't return until error or end of file or buffer has been completely filled or a line feed is encountered, whichever occurs first.

But beyond that, just on general principle, you shouldn't mix fgets() with select(), because fgets() works at a higher level (of buffering). If you're going to use select(), then use read() instead.

Another problem, which may be contributing to your symptoms, is that you need to reset the file descriptor set each time through the loop. The safest way is to reset it completely each time, thus:

Code:

FD_ZERO(&rx_set);
FD_SET(sock,&rx_set);

This should appear just before the select() call, each time through the loop.

Also, what's the value of tv? (TV is worthless, but I'm not talking about that here.) If you don't want timeout at all, but instead want to wait forever for something to happen, don't say &tv; say NULL instead.

If you want to return immediately instead of waiting, set the fields of tv to zero.

If you use &tv (whether zero or nonzero), you must set the value of tv each time through the loop, just before select(), just like rx_set.

Before continuing, please please please do this, and read the page carefully:

Code:

man 2 select
Hope this helps.

nc3b 05-14-2007 07:54 AM

Yup, thank you. Before you posted, I have made some changes. I am resetting rx_set at each loop and I am reading with read().

I could have used fread and fgets, by getting the number of characters to read without blocking using ioctl, but I decided that for now, read() is best.

By the way, thanks for explaining, but I have read the man page for select (every time I'm not sure what a function does I read some documentation), it's just that the server wasn't sending the damn newline (it sent some message and then it wouldn't send anything until the client would do so, and because the client didn't do that, the client remained locked.

And tv in my program was fine, it was one second, because for my application it's not ok to block forever. Again, thank you for your post. Cheers.


All times are GMT -5. The time now is 12:14 AM.