很久以前我就用这段代码的原理做了一个基于socket的服务端应用(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(..) 调用的不良副作用......
请告诉我在这件事上我似乎不明白什么?
马丁。