C语言 Linux 在本地环回上将数据包发送到多个目标



我有一个本质上是UDP中继服务器的应用程序。 当中继服务器收到数据包时,它会将其回显到多个中继客户端。 请注意,所有客户端都将是同一台机器上的单独进程,事实上我不希望数据包离开机器。 我目前的方法是使用 127.0.0.1 本地环回并跟踪所有中继客户端,每个中继客户端都在侦听唯一的 UDP 端口。 然后,当数据包传入时,我循环访问客户端列表并将数据包复制到每个客户端。 这工作正常,但不能很好地扩展到我想要支持的数百甚至数千个客户端。 数据包速率通常很慢(每秒 1 次左右(,但可能会有突发。 所以我正在寻找其他选择。 我考虑过的一些:

1( 让所有中继客户端绑定到相同的 UDP 端口号。 我看到过这方面的相互矛盾的信息,有时说所有进程都会收到数据包,而另一些人说 Linux 将使用某种类型的"负载平衡"算法来决定将其交给谁。

2( 本地环回广播。 服务器将发送到 127.255.255.255。 我再次看到这有效,但不起作用。

3(多播。对此了解不多,但如果可以执行与内部环回隔离的组播,这可能是一种选择。

我用 C 语言编写并在 Debian Linux 服务器上运行。

关于如何最好地做到这一点有什么意见吗?

还有第四个选项,bind一次,并使所有服务器实例从同一套接字读取。只有阻止 recv(并且无关(的进程才能接收数据包。

void
run_child(int fd)
{
while (1)
{
char buff[SIZE];
recv(fd, buff, ....);    
do_something(buff);
}
}

int main(void)
{
int fd = create_udp_socket();
for (int i = 0; i < NUM_CHILDS; i++)
{
pid_t p = fork();
if (pid == 0)
{
run_child(fd);
_exit();
}
}
wait_for_children_to_exit();
}

如果工作进程不是通过分叉单个父进程创建的,则可以使用sendmsg(...)SCM_RIGHTS将文件描述符发送给工作进程。(但我推荐分叉方法(

我选择了#1,让所有中继客户端绑定到相同的UDP端口号。 尽管关于Linux决定哪个进程将获得数据包的评论,但我发现他们都收到了每个数据包。 也许这是TCP和UDP之间的区别? 此外,即使没有SO_REUSEPORT选项,它也可以工作。 这对我来说没有意义,因为它应该在bind()错误时返回. 无论哪种方式,它都可以按照我在 Debian 上想要的方式工作。

最新更新