线程服务器,在客户端之间发送消息

时间:2011-05-30 07:22:47

标签: c multithreading networking tcp pthreads

我正在编写一个C网络服务器,它将两个客户端配对,并允许它们相互发送消息。

目前,每个客户端在服务器中都有自己的线程,在线程中我有一个基本上是while((numBytesRead = read(fd, buffer, 1024)) > 0)的循环。这工作正常,我能够接收消息,然后将它们回送给客户端。

我的问题是,我不确定通过服务器将消息从一个客户端传输到另一个客户端的最佳方式。

我认为我最大的问题是read()阻塞,所以在客户端向服务器发送一些文本以便读取停止阻止之前,我将无法向客户端发送消息。

这有什么办法吗?我最初的想法是让一个线程从客户端读取,一个用于写入客户端,但如果读取在一个线程中阻塞,然后我尝试写入相同的文件描述符,那么这不会导致问题吗?

感谢任何帮助!! :)

3 个答案:

答案 0 :(得分:2)

read仅阻止未发送数据的客户端的线程;所以你理论上可以使用刚发送数据到write的客户端的线程到另一个。

另一种方法可能是使客户端套接字无阻塞,如果流中没有数据,则会导致读取立即返回(有错误)。然而,这是非常耗费处理器的,因为两个套接字都在不断地被探测数据,并且(几乎总是)不返回。

我要查看的地方的最终建议是select函数,该函数可用于检查一组文件描述符并阻塞,直到它们中的任何一个在流中有数据;此外,它可以传递超时(阻止多长时间的上限)。算法的草图可能是:

  1. 选择(客户端套接字,100毫秒)
  2. 为每个具有可用数据的套接字:
    1. 阅读数据
    2. 将其存储在其他套接字的输出缓冲区
  3. 每个插座的
    1. 写入其当前输出缓冲区
  4. 重复

答案 1 :(得分:1)

这当然不是一个简单的问题

  1. 设计协议和协议消息格式
  2. 从套接字
  3. 读取协议消息
  4. 处理类型为“login”的消息
  5. 将uniq id绑定到此套接字
  6. 从套接字(发送方)中读取“消息”类型的其他消息,其中包含“接收方ID”
  7. 找到一个带有该ID的接收器(接收器)
  8. 将消息中的数据发送给接收方
  9. 建议使用IO multiplex而不是多线程。

答案 2 :(得分:0)

使用非阻塞操作是服务器设计的不错选择。在这种情况下,最简单的方法是使用select或poll。更高级的是kqueue(FreeBSD)和epoll(Linux),也可以使用异步I / O(AIO)

因此,如果选择select(),则可以使用下一种方法(例如,类似伪代码):

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);
           }
     }
}