Windows Server 2008中的奇怪套接字行为

时间:2012-07-05 10:55:03

标签: c# .net windows sockets tcp

很久以前我使用这段代码的原理创建了一个基于套接字的服务器应用程序(IP地址和端口常量仅用于测试):

   ...
   _mainSocket = new Socket(AddressFamily.InterNetwork, 
                            SocketType.Stream, ProtocolType.Tcp);

   _mainSocket.SetSocketOption(SocketOptionLevel.IP, 
                               SocketOptionName.ReuseAddress, 1);

   IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("192.168.1.103"), 77);

   _mainSocket.Bind(endPoint);

   _mainSocket.Listen(5);

   _mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
   ...

直到最近,当客户在Windows Server 2008计算机上安装该服务并尝试从另一个网络(即通过一个或多个路由器)连接到该服务时,它已经运行了很多年。

令人惊讶的是,这是不可能的!

进一步分析显示,根本原因是 TTL (IP数据包标题中的生存时间参数)被设置为 1 所有来自我服务的回复数据包,都会有效地将它们丢弃在他们遇到的第一个路由器上。

有趣的是,如果我删除 SetSocketOption(...)调用,TTL会返回到因果128!

这种奇怪的行为似乎只出现在Windows Server 2008中.Windows XP和Windows 7都保持在TTL = 128,正如我所期望的那样。我认为没有理由为什么应该使用“ReuseAddress”选项更改TTL。谁能解释一下?

我还可以通过在第一个之后添加第二个 SetSocketOption(...)调用将TTL恢复为128:

_MainSocket.SetSocketOption( SocketOptionLevel.IP,
                             SocketOptionName.DontRoute, 0).

这有效地抵消了第一个SetSocketOption(..)调用的不必要的副作用......

请告诉我在这件事上我似乎并不理解?

马丁。

1 个答案:

答案 0 :(得分:1)

SocketOptionName的MSDN页面上发布的这个模糊看起来有些启发,虽然我还没有确认:

  

使用.NET阅读.NET Framework源代码时的误解   反射器使用Red Gate的.NET Reflector解码.NET中的类Socket   框架v2.0 ......

     

...

     

为什么那是ReuseAddress而不是IpTimeToLive?

     

事实上:

     

SocketOptionName.IpTimeToLive == SocketOptionName.ReuseAddress == 4

如果以某种方式出现这种情况,则可以解释为什么TTL设置为1 - 这就是您为ReuseAddress传入的值。