【发布时间】:2010-10-14 02:30:58
【问题描述】:
我已经为 TCP 服务器编写了一次监听一个客户端的 C 代码。但我很难弄清楚如何让服务器同时监听多个客户端。
有没有人知道一个很好的教程或例子来解释这个?
谢谢!
【问题讨论】:
-
您使用的是什么平台?
我已经为 TCP 服务器编写了一次监听一个客户端的 C 代码。但我很难弄清楚如何让服务器同时监听多个客户端。
有没有人知道一个很好的教程或例子来解释这个?
谢谢!
【问题讨论】:
有很多方法可以实现这一点,其中一些是:
select 基本上等待一组文件描述符,直到其中一个准备好读取或写入。pthreads)将各个会话移交给一个进程中的单独线程。fork 复制处理会话的进程,以便分叉的进程处理该会话,而原来的进程返回等待更多连接。其中,我更喜欢中间那个。分叉一个进程有时是一项昂贵的操作,因为如果任何一个进程试图更改数据,通常都必须复制数据。
select 选项意味着您的代码必须管理多个会话,这有时会变得混乱。
使用线程,您可以相对轻松地将会话彼此分开,而不会产生流程重复的成本。当然,如果您不小心,线程也有其自身的缺陷,但是一旦您了解了潜在的问题区域,我认为它是一个更可取的选择。
【讨论】:
看看 libevent。它支持多种流行的高可扩展性服务器应用程序。
【讨论】:
结帐http://www.zeromq.org/ 这是一个非常酷的网络(或消息传递)库,它将“选择”或传统套接字从代码中移除。
【讨论】:
你在哪个平台上?如果是 Windows,一个流行的平台 API 是WaitForMultipleObjectsEx。如果是 Linux,从低级到高级的流行选择可能是 select(如 Joshua 所述)、epoll、kqueue 或 libevent/libev(类似但略有不同的库)上述 API 之上的其他事物抽象层)。
select 非常便携,但在大多数情况下并不是最佳的(自创建以来已经学到了很多东西)。尽管如此,如果您不需要疯狂的性能并且想要坚持非常标准的 C 编程,那将是一个不错的选择,并且有大量的文献提到它。一旦您的服务器使用 select,将其更改为更高级的多路复用 API 之一应该不会太难。
【讨论】:
在前一个监听器被占用时创建另一个监听器
【讨论】:
见 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);
}
}
}
}
【讨论】:
不知道这是否与此有关,但...可以使用以下变体:
listener.Start()
While True
Dim user As New chatclient(listener.AcceptTcpClient)
End While
【讨论】: