SocketException:在IIS 7下强制关闭现有连接,但在IIS 6下正常

时间:2014-01-31 00:56:11

标签: c# sockets tcp iis-7.5 iis-6

我们已经在IIS 6 / Windows Server 2003下运行了几年的.ashx应用程序。我们最近一直试图让一些新服务器启动并运行,并且需要迁移到Win 2k8 R2和IIS 7.5,但是我有一段时间让应用程序在新服务器上运行良好。

.ashx是我们通过TCP进行会话的自定义消息排队引擎的Web解释器。因此,在.ashx内部,我们创建了一个与消息队列服务器通信的套接字。关于这个体系结构的任何内容都没有改变,但是我在运行.Net 4的Win 2k8和IIS 7.5设置上遇到的错误是

  

System.Net.Sockets.SocketException(0x80004005):现有的   连接被远程主机强行关闭   System.Net.Sockets.Socket.Receive(Byte [] buffer,SocketFlags   的SocketFlags)

我们不会在较旧的设置上出现此错误 - 相同的代码,尽管它正在运行.Net 3.5运行时。

请记住,这个错误不会从面向HTTP的套接字抛出,而是从尝试与消息队列服务器通信的套接字抛出。我已经通过在Web服务器上运行“原始”telnet会话到消息队列来验证我不相信我有防火墙问题,并且能够成功地与消息队列进行交互。

以下是我们设置套接字的方法:

            this.m_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            System.Net.IPAddress ip = System.Net.IPAddress.None;

            // Before bothering the DNS server, try to parse numeric IP
            try
            {
                ip = System.Net.IPAddress.Parse(host);
            }
            catch (FormatException)
            {
                // Not a numeric IP.  Do the DNS lookup.
                // (BTW: DNS lookup will convert the IP, but only after a failing lookup, which is slow)
                IPHostEntry ipadd = System.Net.Dns.GetHostEntry(host);
                // (Note: That lookup might fail.  It'll throw a SocketException.)
                ip = ipadd.AddressList[0];
            }
            try
            {
                this.m_sock.Connect(ip, port);
                this.m_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
                this.m_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.NoDelay, true);
                this.m_sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
                this.m_sock.ReceiveTimeout = 60 + this.m_timeout;
                this.m_sock.Blocking = true;
                this.m_sock.ReceiveBufferSize = 65536;
                this.m_sock.SendBufferSize = 65536;
                if (ok != "" && !this.m_isweb)
                {
                    Console.WriteLine(ok);
                }
                break;
            }
            catch (SocketException)
            {
                this.m_sock.Close();
                this.m_sock = null;
            }

现在是一个“ReadSome”方法的片段,它在this.m_sock_Receive上爆炸了我们:

            if (this.m_sock.Poll(1000000, SelectMode.SelectRead))
            {
                n = this.m_sock.Available;
                if (n == 0)
                    n = 1;      // Presume at least one byte readable
                if (max > 0 && n > max)
                    n = max;
                byte[] buf = new byte[n];
                int rcvd = this.m_sock.Receive(buf, SocketFlags.None);
                if (rcvd == 0)
                    throw new knetmq_Exception(this, "Read EOF",
                        knetmq_Exception.codes.EOF);

                return buf;
            }

在“接收”发生之前,有一个“发送”无异常发生,但是我没有在另一侧看到有效负载。

感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

哦,欢乐!我修好了!

缺点:我没有设置我的TTL,并且在新服务器上TTL一直被超过。

更深入:新服务器恰好位于略有不同的网络上。因为我们没有设置TTL,所以TTL默认为1. Wirehark发现TTL被反复超出,因此发出了TCP RST,导致错误被抛出。这就是远程主机永远不会收到消息的原因。

我在这个问题上猛烈抨击了2天,所以我希望最终得到SocketException的人能够看到这个并找到TTL问题!