如何将原始套接字绑定到特定端口?

5
我目前正在完成一个编程任务。这个任务是要实现一个客户端、网络模拟器和服务器。客户端将数据包传递给网络模拟器,网络模拟器再传递给服务器。反之亦然。任务的先决条件是我只能使用原始套接字。因此,我将创建自己的IP和UDP头部。我已经使用Wireshark测试了我的数据包。它们都正确且格式正确(它可以正确地读取它们)。
另一个要求是模拟器、客户端和服务器都必须绑定到特定的端口。现在,我不知道如何将原始套接字绑定到特定的端口。所有我的原始套接字都接收主机地址上的所有流量。根据man页和互联网上的所有其他地方,包括Richard Stevens的“Unix网络编程”,这就是它们应该工作的方式。我的老师没有回复我的任何邮件,直到星期二我可能都无法问他。我看到两个选择。首先,我可以使用libpcap从特定设备过滤,然后输出到我的原始套接字。我感觉这超出了我们任务的范围。或者我可以在从套接字接收后对它们进行过滤。这显然会产生很多开销,因为所有数据包都被复制/移动到内核中。至少,这是我的理解(如果我错了,请随时纠正我)。
所以我的问题是: 有什么选项或设置可以做到这一点吗?原始套接字将绑定到一个端口吗?我有没有错过什么明显的东西?
感谢您的时间。
2个回答

5
raw(7)的手册中提到:

使用bind(2)调用可以将原始套接字绑定到特定的本地地址。如果没有绑定,所有指定IP协议的数据包都会被接收。此外,可以使用SO_BINDTODEVICE将RAW套接字绑定到特定的网络设备;请参见socket(7)。

编辑:您不能将原始套接字绑定到特定端口,因为“端口”是TCP和UDP中的概念,而不是IP。查看这三个协议的标头图,就会变得很明显:您正在更低的层次上工作,那里并不知道端口的概念。


所以,为了确保我理解正确,我无法绑定到特定的端口?如果是这样,您将如何实现“过滤器”?将Libpcap绑定到特定设备并过滤端口,或者由于这仅用于作业,只需在套接字接收它们后将其过滤掉?或者您可能有更好的实现方式?顺便说一句,感谢您的回复和时间。 - user614885
请查看我回答中的编辑。我认为你走在了正确的道路上。 - John Zwinck
“端口”是传输协议的一种构造。从网络层面(IP)来看,数据包被寻址到地址。更高级别的传输协议负责实现“端口”的语义。我想你必须自己解码接收到的数据包,以确定它寻址到哪个“端口”,并进行相应的过滤。 - Santa
和圣诞老人一样,感谢您的帮助。我将在程序中使用端口字段进行比较。我还有另一个问题。我是新来的,请问我需要标记这个问题为已回答吗? - user614885

2
我认为你需要在软件中过滤数据包。听起来这个练习是要通过在用户空间重新创建简化的IP堆栈的一部分来了解不同组件的作用。通常在内核中,IP代码会处理所有数据包,验证IP头,重组片段并检查协议字段。如果协议字段是17(udp),则将其传递给UDP代码(每个UDP数据包)。然后由UDP代码验证UDP头,并基于目标端口确定是否有任何应用程序对它们感兴趣。
我想象你的项目期望更多地模仿这个过程。显然,这些操作都不如在内核中执行高效,但既然任务是在用户空间编写(部分)IP堆栈,我猜效率不是练习的重点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接