【问题标题】:Reusing a port number in a UDP在 UDP 中重用端口号
【发布时间】:2010-09-20 21:38:45
【问题描述】:

在 ASIO 中,是否可以创建另一个与另一个套接字具有相同源端口的套接字?

我的 UDP 服务器应用程序正在使用端口 3000 调用 receive_from。它传递了数据包 关闭到将发送响应的工作线程(当前使用动态源端口)。

另一个线程中的套接字是这样创建的:

udp::socket sock2(io_service, udp::endpoint(udp::v4(), 0));

并使用与原始数据包一起保存的 sender_endpoint 响应原始请求。

我希望能够使用与服务器侦听相同的源端口响应客户端。但我看不出如何做到这一点。如果我尝试使用该地址,则会出现异常。可以按照我的要求做吗?我想要这样做的原因是如果我使用动态端口,这意味着客户端需要在 Windows 中添加特殊的防火墙规则以允许读取回复数据包。我发现如果回复中的源端口相同,windows防火墙会允许它回传。

【问题讨论】:

    标签: linux sockets


    【解决方案1】:

    异常告诉你:你不能创建两个具有相同源端口的活动套接字。我不知道 ASIO,但是您应该能够在关闭线程之前创建套接字,保留对套接字和线程的引用以供以后使用,并且一旦数据发送线程空闲,就加入它并发送任何其他东西。

    编辑:通过一点点努力,您还可以创建一个套接字,您不必等到一个线程的全部数据都发送完毕:让一个拥有套接字的工作线程在队列上侦听数据块(理想情况下正是您打算发送的有效负载的大小)并从多个线程将任意有效负载块发送到此队列。

    【讨论】:

    • 我认为这是 BSD 套接字的一大局限。很遗憾你不能这样做。能够创建两个具有相同源端口的套接字对我来说很有意义,但其中只有一个处于侦听状态。这将允许 send_to 为 UDP 工作。看来我得忍受这个限制了。
    • 您可以这样做,只要在同一进程中重用套接字即可。您只是不必一遍又一遍地重新创建 same 设备。对同一过程的限制是一件好事,恕我直言
    • @knitti,如果那是真的,那么我不会得到例外!
    • 我想要多个具有相同源端口的套接字。其中将有大约 7 个,它们只会在同一端口上发送 + 一个其他套接字,而该端口只会接收。这似乎是不可能的。
    • 如果第二个进程通过fork() 继承绑定的套接字,或者通过UNIX 域套接字使用SCM_RIGHTS 消息传递它,甚至可以将它们放在多个进程中。
    【解决方案2】:

    您应该能够使用 SO_REUSEADDR 套接字选项将多个套接字绑定到同一个地址。但是话虽如此,你不想这样做,因为它没有指定哪个套接字将接收该端口上的传入数据(你必须检查所有套接字的传入数据)

    更好的选择是使用同一个套接字来发送回复 - 这可以安全地从多个线程完成,无需任何额外的同步(因为您使用的是 UDP)。

    【讨论】:

    • 不,那不是该选项的用途。见:unixguide.net/network/socketfaq/4.5.shtml
    • 那么您尝试过吗(在带有 UDP 套接字的 Linux 上)?你可能会大吃一惊……
    • 其实你是对的。我做错了,因为我错误地初始化了 boost。它确实有效,但正如您所指出的,它会导致问题并且确实有效。
    【解决方案3】:

    发送回复到同一个套接字(你收到客户端的请求)而不是创建新的 但请确保不要同时从两个线程发送到同一个套接字

    【讨论】:

    • 谢谢。似乎这是唯一可以做到的方法。但由于我的应用程序的性质和负载,我将保留具有不同端口号的独立套接字。
    猜你喜欢
    • 1970-01-01
    • 2013-03-27
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-03
    • 2011-04-22
    相关资源
    最近更新 更多