【问题标题】:TCP server listen to mulitple clients at once in CTCP服务器在C中一次监听多个客户端
【发布时间】:2010-10-14 02:30:58
【问题描述】:

我已经为 TCP 服务器编写了一次监听一个客户端的 C 代码。但我很难弄清楚如何让服务器同时监听多个客户端。

有没有人知道一个很好的教程或例子来解释这个?

谢谢!

【问题讨论】:

  • 您使用的是什么平台?

标签: c tcp


【解决方案1】:

有很多方法可以实现这一点,其中一些是:

  • 使用select 基本上等待一组文件描述符,直到其中一个准备好读取或写入。
  • 使用线程(例如pthreads)将各个会话移交给一个进程中的单独线程。
  • 使用fork 复制处理会话的进程,以便分叉的进程处理该会话,而原来的进程返回等待更多连接。

其中,我更喜欢中间那个。分叉一个进程有时是一项昂贵的操作,因为如果任何一个进程试图更改数据,通常都必须复制数据。

select 选项意味着您的代码必须管理多个会话,这有时会变得混乱。

使用线程,您可以相对轻松地将会话彼此分开,而不会产生流程重复的成本。当然,如果您不小心,线程也有其自身的缺陷,但是一旦您了解了潜在的问题区域,我认为它是一个更可取的选择。

【讨论】:

    【解决方案2】:

    看看 libevent。它支持多种流行的高可扩展性服务器应用程序。

    【讨论】:

      【解决方案3】:

      结帐http://www.zeromq.org/ 这是一个非常酷的网络(或消息传递)库,它将“选择”或传统套接字从代码中移除。

      【讨论】:

        【解决方案4】:

        你在哪个平台上?如果是 Windows,一个流行的平台 API 是WaitForMultipleObjectsEx。如果是 Linux,从低级到高级的流行选择可能是 select(如 Joshua 所述)、epollkqueuelibevent/libev(类似但略有不同的库)上述 API 之上的其他事物抽象层)。

        select 非常便携,但在大多数情况下并不是最佳的(自创建以来已经学到了很多东西)。尽管如此,如果您不需要疯狂的性能并且想要坚持非常标准的 C 编程,那将是一个不错的选择,并且有大量的文献提到它。一旦您的服务器使用 select,将其更改为更高级的多路复用 API 之一应该不会太难。

        【讨论】:

          【解决方案5】:

          在前一个监听器被占用时创建另一个监听器

          【讨论】:

            【解决方案6】:

            见 man 2 选择

            这应该做你想做的事。当心,未经测试:

            listen_any(int n, int *s, void receiver(int *))
            {
                FD_SET set;
                int x = -1;
                int i;
                for (i = 0; i < n; ++i)
                    if (x < s[i]) x= s[i];
                while (1) {
                    FD_ZERO(&set);
                    for (i = 0; i < n; ++i)
                        FD_SET(s[i], fd);
                    select(x, &set, NULL, NULL, NULL);
                    for (i = 0; i < n; ++i)
                        if (FD_ISSET(s[i], fd)) {
                            struct socakddr sa;
                            int len = sizeof(sa);
                            int sn = accept(s[i], &sa, &len);
                            if (sn >= 0) {
                                if (!receiver(sn))
                                   close(sn);
                            }
                        }
                }
            }
            

            【讨论】:

              【解决方案7】:

              不知道这是否与此有关,但...可以使用以下变体:

              listener.Start()
              While True
                  Dim user As New chatclient(listener.AcceptTcpClient)
              End While
              

              【讨论】:

                最近更新 更多