两个 TCP 套接字之间的基于内核 (Linux) 的数据中继 [英] kernel-based (Linux) data relay between two TCP sockets

查看:36
本文介绍了两个 TCP 套接字之间的基于内核 (Linux) 的数据中继的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了 TCP 中继服务器,它的工作原理类似于对等路由器(超级节点).

I wrote TCP relay server which works like peer-to-peer router (supernode).

最简单的情况是两个打开的套接字和它们之间的数据中继:

The simplest case are two opened sockets and data relay between them:

clientA <---> 服务器 <---> clientB

但是服务器必须提供大约 2000 个这样的 A-B 对,即.4000 个套接字...

However the server have to serve about 2000 such A-B pairs, ie. 4000 sockets...

userland 中有两个众所周知的数据流中继实现(基于 socketA.recv() --> socketB.send()socketB.recv() --> socketA.send()):

There are two well known data stream relay implementations in userland (based on socketA.recv() --> socketB.send() and socketB.recv() --> socketA.send()):

  • select/poll 函数的使用(非阻塞方法)
  • 使用线程/分叉(阻塞方法)
  • using of select / poll functions (non-blocking method)
  • using of threads / forks (blocking method)

我使用了线程,所以在最坏的情况下,服务器会创建 2*2000 个线程!我不得不限制堆栈大小并且它有效,但这是正确的解决方案吗?

I used threads so in the worst case the server creates 2*2000 threads! I had to limit stack size and it works but is it right solution?

我的问题的核心:

有没有办法避免在用户态的两个套接字之间进行活动数据中继?

似乎有一种被动的方式.例如,我可以从每个套接字创建文件描述符,创建两个管道并使用 dup2() - 与 stdin/out 重定向相同的方法.那么两个线程对于数据中继没有用,可以完成/关闭.问题是服务器是否应该关闭套接字和管道,以及如何知道管道何时损坏以记录事实?

It seems there is a passive way. For example I can create file descriptor from each socket, create two pipes and use dup2() - the same method like stdin/out redirecting. Then two threads are useless for data relay and can be finished/closed. The question is if the server should ever close sockets and pipes and how to know when the pipe is broken to log the fact?

我还发现了套接字对",但我不确定它是否适合我的目的.

I've also found "socket pairs" but I am not sure about it for my purpose.

您建议采用什么解决方案来卸载用户空间并限制线程数量?

一些额外的解释:

  • 服务器已定义静态路由表(例如 ID_A 和 ID_B - 配对标识符).客户端 A 连接到服务器并发送 ID_A.然后服务器等待客户端 B.当 A 和 B 配对(两个套接字都打开)时,服务器开始数据中继.
  • 客户端是对称 NAT 背后的简单设备,因此 N2N 协议或 NAT 穿越技术对它们来说太复杂了.

感谢 Gerhard Rieger,我得到了提示:

我知道避免读/写、接收/发送的两种内核空间方式用户空间:

I am aware of two kernel space ways to avoid read/write, recv/send in user space:

  • 发送文件
  • 拼接

两者都有关于文件描述符类型的限制.

Both have restrictions regarding type of file descriptor.

dup2 不会帮助在内核中做一些事情,AFAIK.

dup2 will not help to do something in kernel, AFAIK.

手册页:splice(2) splice(2) vmsplice(2) sendfile(2) tee(2)

相关链接:

推荐答案

OpenBSD 实现 SO_SPLICE:

OpenBSD implements SO_SPLICE:

Linux 支持类似的东西还是只有自己的内核模块才是解决方案?

这篇关于两个 TCP 套接字之间的基于内核 (Linux) 的数据中继的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆