Jonas Schnelli
Jonas Schnelli

Reputation: 10005

bidirectional socket (non-blocking) with c

i try to do a kind-of chat over TCP sockets. The server side is implemented in php and (should) work fine.

No i've encountered a problem on the client side (implemented in c [c99]):

i'd like to listen (read) for "new bytes" from the server and i also would like to send (write) "some bytes" to the server whenever the user did enter new data.

Now the question: -> how do i listen for incoming traffic (read) and still be able to call every 1 seconds a callback where i can check for new bytes to send to the server? I know that i have to use select (system call) but i do not have a idea how to handle the timeout etc. select is also blocking for a certain time.

Thanks for any example.

Upvotes: 1

Views: 2179

Answers (3)

Some programmer dude
Some programmer dude

Reputation: 409166

There is a function called select that can be used for this. It can check if there is new input on a socket to read, and it has a timeout so it can be used for your timer as well.

It exists on one form or other on all major operating systems. Just do a Google search for socket select <your operating system> example and you will get a boat-load of results.


The last argument to select is used for the timeout. It's a pointer to a struct timeval, a structure which contains fields to set the timeout.

If this pointer is passed as NULL then there is no timeout, and select can block indefinitely.

To set a timeout, you need to set the tv_sec field of the timeval structure to the number of seconds, and the tv_usec field to the number of microseconds (must be less than one million). You can have a timeout of zero, i.e. just a quick poll, by setting these fields to zero.

If select returns zero, then there was a timeout.

Example, with a 1.5 second timeout:

for (;;)
{
    fd_set readset;
    int maxfd;

    /* Initialize and set `readset` and `maxfd` */

    struct timeval tv;
    tv.tv_sec  = 1;
    tv.tv_usec = 500000;

    int res = select(maxfd + 1, &readset, NULL, NULL, &tv);

    if (res == -1)
        perror("select");  /* Error */
    else if (res == 0)
    {
        /* Timeout, do something */
    }
    else
    {
        /* A socket in `readset` is readable */
    }
}

If select returns before the timeout, the timeval structure is modified to contain the time remaining of the timeout.

Upvotes: 1

Brett Hale
Brett Hale

Reputation: 22318

Use the select system call, with the timeout parameter set as needed. Beej's guide is still a good source with plenty of example code.

Upvotes: 0

ziu
ziu

Reputation: 2720

Use the select system call. You could also find this useful.

Upvotes: 0

Related Questions