【问题标题】:Only one use of each socket address (proto/ip/port)每个套接字地址(proto/ip/port)只使用一次
【发布时间】:2016-01-17 20:44:39
【问题描述】:

大家好

信息:

主题:组播

首先,我找到了解决方案,但我不明白为什么这是解决方案。

**范围:**(删除任何杂乱/不必要的代码)

new_socket()
{
    //SND_LOCAL_IP = 10.0.0.30 - local network adapter's IP
    //SND_MCAST_PORT = 80 port used to broadcast Multicast Packets 

    //_SND_LOCAL_EP = new IPEndPoint(SND_LOCAL_IP, SND_MCAST_PORT);  <problem>                                       
    _SND_LOCAL_EP = new IPEndPoint(SND_LOCAL_IP, 0);                 <fixed>    
}

init_socket()
{
    _SND_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    _SND_Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_SND_MCAST_IP, _SND_LOCAL_IP));
    _SND_Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
    _SND_Socket.ExclusiveAddressUse = false;
    _SND_Socket.Bind(_SND_LOCAL_EP);      <<< ====== PROBLEM LINE=====
}

问题:

我的侦听器在 form_load 事件上单独运行在线程上,因此它的初始化方式与我的 SND_Socket 相同,但是将 SND_Socket.Bind() 端口更改为 0 允许我接收这些多播数据包。

正如def MSDN 所说,添加 ExclusiveAddress 不应缓解此问题(因为接收和发送套接字的初始化方式相同)。

如果 Socket 只允许一个套接字绑定到特定端口,则为 true;否则为假。 Windows Server 2003 和 Windows XP Service Pack 2 的默认值为 true,所有其他版本的默认值为 false。

进一步,在备注中证实了这一点:

如果 ExclusiveAddressUse 为 false,则多个套接字可以使用 Bind 方法绑定到特定端口;然而,只有一个套接字可以对发送到端口的网络流量执行操作。如果多个套接字尝试使用 Bind(EndPoint) 方法绑定到特定端口,则具有更具体 IP 地址的套接字将处理发送到该端口的网络流量。

如果 ExclusiveAddressUse 为真,第一次使用 Bind 方法尝试绑定到特定端口,无论 Internet 协议 (IP) 地址如何,都会成功;所有后续使用 Bind 方法尝试绑定到该端口的操作都将失败,直到原始绑定的套接字被销毁。

此属性必须在调用 Bind 之前设置;否则会抛出 InvalidOperationException。

为什么这样做

Socket.ExclusiveAddress = false

不允许SND_Socket作为“Listener_Socket”监听这个IP和端口,为什么RCV_Socket.Bind()中设置端口为0可以解决这个问题?

【问题讨论】:

  • 将 ReuseAddress 错误更新为问题中的 ExclusiveAddress

标签: c# sockets networking


【解决方案1】:

如果没有一个好的Minimal, Complete, and Verifiable Example,就不可能确定你甚至具体遇到了什么问题,更不用说确定原因是什么了。缺乏这一点,一些与所述问题相关的观察/cmets:

  1. ExclusiveAddressUse 属性不影响设置它的套接字,但影响该套接字之后绑定的任何其他套接字。它可以防止任何其他套接字使用相同的端口号,也就是说,它本来可以通过 ReuseAddress 套接字选项来做到这一点。
  2. ReuseAddress 套接字选项确实影响设置它的套接字。它允许一个套接字绑定到同一个适配器上的其他套接字已经绑定的同一个端口。
  3. 通常不会同时使用这两个选项。要么您希望套接字合作,其中一个允许另一个套接字重用相同的端口号,或者您希望禁止任何其他套接字使用相同的端口号。
  4. 绑定到端口0 在某些情况下可以缓解滥用地址独占性选项时可能出现的问题。对于不完整的问题,我无法推断您遇到了什么具体问题。但是绑定到端口0会导致套接字选择一个唯一的端口号,这当然可以避免端口号冲突的任何问题。
  5. 除此之外,我在您的代码中看到的最大问题是您在致电Bind() 之前尝试加入多播组。你应该反过来做,即绑定套接字,然后然后加入多播组。
  6. 很可能,您根本不应该使用ReuseAddress。您的套接字应该有唯一的端口号。您可以使用ExclusiveAddressUse,作为一种预防措施,以确保在某些代码确实尝试将套接字绑定到已在使用的端口时出现异常。

我建议您密切按照 MSDN 上 the documentation page for the MulticastOption Class 上的示例开始。一旦有了使用该代码的工作示例,您就可以调整代码以满足您的特定需求。

【讨论】:

  • 对我来说把所有的代码都放好了,它会比预期的要长得多;)。感谢您的详细解释,这确实有很大帮助。我会注意这一点并改变需要改变的地方!
  • 这是我见过的对这两个选项最好的解释。
猜你喜欢
  • 1970-01-01
  • 2014-01-16
  • 1970-01-01
  • 1970-01-01
  • 2014-05-29
  • 1970-01-01
  • 2023-03-30
  • 2022-11-26
  • 2013-03-01
相关资源
最近更新 更多