前几天在做p2p TCP穿透的时候,发现了一个很严重的一个问题,由于需要做点对点穿透,无法预知外网IP和内网IP哪个会被连接,所以 P点 机器上使用了 socket.bind(IPAddress.Any, port); 并且使用端口复用,socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); //设置端口可重用 。以下称A机器,B机器,S服务器。A向B做穿透连接。
在B的同一个端口上,启动了连接S服务器的socket 和一个监听另一个P机器连接的socket ,但是问题出现了,在服务器S帮忙穿透后,A向B连接时,出现了无法连接,服务器积极拒绝的情况。后来在局域网中测试,发现把B的 bind 的 IPAddress.Any, 改成 固定的内网IP后,没有出现那种情况。
刚开始很郁闷,不是IPAddress.Any 可以在任何IP接口上启动监听吗,怎么不行?
一想,可能是B的端口复用上出现了问题,因为在同一个端口上绑定了另外一个Socket , 当然,端口复用不是问题所在,而是在端口复用的另一个Socket 上 (与 S 做连接的Socket ) 绑定的是固定的内网IP,而不是IPAddress.Any 。 具体也不知道原理,我猜想可能是绑定固定IP的SOCKET 比较优先吧,所以导致另一个复用的端口不能正常在IPAddress.Any 监听。后来,把那个绑定固定IP的SOCKET 也改成IPAddress.Any 就没有出现问题了。
情况复杂,说得比较乱,完全是自己备忘和给有心人提个醒。
为这个问题郁闷了半天,下班回家晚上快睡觉的时候,慢慢整理出一个头绪,想到可能可以解决的办法。
后来查了资料,才明白了原理:端口复用时,当连接到来时,按最明确及最近绑定的原则将连接交给某一个应用处理