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 work开发者_如何学运维s 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!! :)
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:
- select( client-sockets, 100ms )
- for each socket with available data:
- read the data
- store it in the other socket's output-buffer
- for each socket:
- write its current output buffer
- repeat
this is certainly not a simple question
- design a protocol and protocol message format
- read protocol message from socket
- deal with message with type of "login"
- bind an uniq id to this socket
- read other messages of type "message" from socket(sender), which contain a "receiver id"
- find a socket with that id(receiver)
- send the data in the message to receiver
suggest using IO multiplex instead of multi threaded.
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);
}
}
}
精彩评论