views:

127

answers:

6

I've made a piece of code in what's on my server as multiple threads

The problem is that it doesn't send data while im receiving on the other socket.

so if i send something from to client 1 to client 2, client2 only receives if he sends something himself(jumps out of the recv function) .. how can i solve this ?

 /* Thread*/
while (! stop_received) {
        nr_bytes_recv = recv(s, buffer, BUFFSIZE, 0);

        if(strncmp(buffer, "SEND", 4) == 0) {
            char *message = "Text asads \n";
            rv = send(users[0].s, message, strlen(message), 0);
            rv = send(users[1].s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }           
        }else{
            char *message = "Unknown command \n";
            rv = send(s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }
        }
}
+1  A: 

Put send and receive in separate threads.

Undeph
+2  A: 

Your code will block on the recv() call. Either write a multi-threaded application, or investigate the use of the select() function.

anon
+6  A: 

To be a little more specific, there are a few types of I/O. What you're doing currently is called blocking i/o. In general that means that when you call send or recv the operation will "block" until it has completed.

In contrast to that there is what is known as non-blocking i/o. In this i/o model an operation will return immediately if it's unable to complete. Typically the select function is used with this i/o model.

You can see an example program here at the Select Tutorial. The full source code is at the bottom of the page.

As others have noted, your other option is to use threads.

Robert S. Barnes
+1: `select` is the way to go for such a common pattern.
ereOn
A: 

You shoud separete the code in two threads, one transmitter and one receiver.

Somewthing like this:

 /* 1st Thread*/
while (! stop_received) {
        nr_bytes_recv = recv(s, buffer, BUFFSIZE, 0);
}


 /* 2nd Thread*/
while (! stop_received) {
        if(strncmp(buffer, "SEND", 4) == 0) {
            char *message = "Text asads \n";
            rv = send(users[0].s, message, strlen(message), 0);
            rv = send(users[1].s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }           
        }else{
            char *message = "Unknown command \n";
            rv = send(s, message, strlen(message), 0);
            if (rv < 0) {
                perror("Error sending");
                exit(EXIT_FAILURE);
            }
        }
}

The concurrency will bring some issues, like access to the buffer variable.

pcent
A: 

There are two ways of achieving the goal you want:

1.) implement the sending and receiving codes in different threads. but there will be some issues, like increasing no of clients might get you into troubles to handle the code. also there will be some some problem of concurrency (as mentioned by pcent). you can go for no blocking sockets but i suggest not to do so, as i hope you dont want a cpu hog.

2.) The other way is to use of select() function which will let you monitor multiple sockets of different types at the same time. for more description of "select()" you can google it. :)

Kumar Alok
+1  A: 

I notice that you are using perror() (the POSIX error function), which leads me to believe you are using a POSIX operating system, which makes me suspect its GNU/Linux.

select() is portable, poll() is POSIX centric and epoll() is Linux centric. If using GNU/Linux, I strongly suggest avoiding select() and using:

  • poll() if you are polling only a few dozen file descriptors
  • epoll() if you need to scale to thousands of connections, and its available.

If your application need not be portable, and no requirement prohibits using extensions, use poll() or epoll(). Once you learn how select() works, you'll be very happy to get rid of it, especially for something that has to scale to serve many clients.

If portability is a requirement, see if either poll() or epoll() exist during your build configuration and use either in favor of select().

Note, epoll() did not appear until Linux 2.5(something), so its best to get used to using both.

Tim Post
`poll` is a [POSIX function](http://www.opengroup.org/onlinepubs/000095399/basedefs/poll.h.html#tag_13_35).
dreamlax
@dreamlax - correct, updated.
Tim Post