Reputation: 2225
I'm writing a C network server that will pair two clients together and allow them to send messages to each other.
At the moment, each client has their own thread in the server and in the thread I have a loop that is basically while((numBytesRead = read(fd, buffer, 1024)) > 0)
. This works fine and I am able to receive messages and then echo them back to the client.
My problem is though that I'm not sure the best way of transferring a message from one client to another through the server.
I think my biggest issue is that read()
blocks, so I won't be able to send a message to a client until the client sends some text to the server so that read stops blocking.
Is there any way around this? My initial thought was to make one thread for reading from the client and one for writing to the client but if read is blocking in one thread and then I try to write to the same file descriptor then won't this cause issues?
Appreciate any help!! :)
Upvotes: 3
Views: 1862
Reputation: 634
Using non-blockin operation is good choice for server design. In this case the simplest way is using select or poll. More advanced is kqueue (FreeBSD) и epoll (Linux), also asynchronous I/O (AIO) could be used
So if select() is the choice, the next approach could be used (just example, something like pseudo code):
fd_set read_set, write_set;
struct timeval timeout;
while(!quit)
{
// adds your sockets to fd_set structure, return max socket + 1, this is important!
max = fillFDSet(&read_set);
setReadTimeout(&timeout); // sets timeout for select
if (0 < select(max, &read_set, NULL, NULL, &timeout)) // wait for read
{
// there is at least one descriptor ready
if (FD_ISSET(your_socket))
{
socket_size = read(socket, socket_buffer, 1024);
}
}
max = fillFDSet(&write_set);
setWriteTimeout(&timeout); // sets timeout for select
if (0 < select(max, NULL, &write_set, NULL, &timeout)) // wait for write
{
// there is at least one descriptor ready
if (FD_ISSET(your_socket))
{
write(socket, socket_buffer, socket_size);
}
}
}
Upvotes: 0
Reputation: 2337
this is certainly not a simple question
suggest using IO multiplex instead of multi threaded.
Upvotes: 1
Reputation: 3891
read
only blocks the thread of the client that isn't sending data; so you can in theory use the thread of the client that just sent data to write
to the other.
An alternative may be to make the client sockets be non-blocking, which causes the read to return immediately (with error) if there is no data in the stream. However this is very processor-intensive as both sockets are continually being probed for data and (almost always) returning with none.
My final suggestion for places to look is at the select
function, which can be used to check a set of file descriptors and block until any of them have data in the stream; and additionally it can be passed a timeout (an upper limit for how long to block). A rough sketch of an algorithm might be:
Upvotes: 2