客户端关闭时,NetworkStream会在Read()上抛出异常

时间:2013-01-27 21:26:45

标签: c# sockets networkstream

我在创建的应用中遇到了一些问题。一般情况(以下描述与问题无关):我有一个WCF客户端 - 服务器应用程序,用于收集多个站点的数据。客户端检索本地数据(某些文件等),将其发送到数据中心的服务器,然后该服务器对其进行处理。客户端从localhost获取大部分数据,但其中一些数据是从LAN上的不同服务器检索的。这是我的问题开始的地方。我必须创建一个第三个应用程序,它将数据发送到指定的客户端。在这篇文章的提醒中,我将客户端和服务器称为同一LAN上的应用程序(因此不是上面数据中心中的服务器)

我尝试使用命名管道,它在同一台主机上进行了极好的进程间处理,但服务器到服务器的速度非常慢。 (如果有人想到为什么这是plz不要犹豫告诉我。一些测试上升到1000毫秒发送和接收只有几个字节)

所以我开始使用TcpClient类。测试表明响应速度比NP等价物快得多,所以我决定选择这个选项。

现在,当客户端和服务器按原样开始和结束时,一切都很好。当服务器启动,客户端已连接,服务器正在等待其stream.Read()方法,然后客户端应用程序退出时,问题就出现了:

Unable to read data from the transport connection: De externe host heeft een verbinding verbroken.(第二部分翻译:远程主机强行关闭现有连接。)

目前我用Try-Catch语句包装整个部分,在IoException上重新启动整个部分。这确实有效,但是当我读到几篇关于“异常应该是特殊的东西!”的帖子时,它感觉不舒服。

最后问题是:如何避免这种异常? (在现实生活中保持服务器和客户端应用程序之间连接的正常方法是什么?)

服务器     TcpListener serverSocket = new TcpListener(System.Net.IPAddress.Any,8888);             TcpClient clientSocket = default(TcpClient);

        while (true)
        {
            serverSocket.Start();
            clientSocket = serverSocket.AcceptTcpClient();

            while ((true))
            {
                try
                {
                    NetworkStream networkStream = clientSocket.GetStream();
                    byte[] bytesFrom = new byte[10025];
                    networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);//THIS THROWS THE EXCEPTION WHEN A CLIENT QUITS
                    string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                    dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                    Console.WriteLine(" >> Data from client - " + dataFromClient);
                    string serverResponse = "Server response " + DateTime.Now.ToString("HH:mm:ss,fff");
                    Byte[] sendBytes = Encoding.ASCII.GetBytes(serverResponse);

                    int len = sendBytes.Length;
                    networkStream.WriteByte((byte)(len / 256));
                    networkStream.WriteByte((byte)(len & 255));

                    networkStream.Write(sendBytes, 0, sendBytes.Length);
                    networkStream.Flush();
                }
                catch (System.IO.IOException ex)
                {
                    Console.WriteLine(ex.ToString());
                    break;
                }

            }
            clientSocket.Close();
            serverSocket.Stop();
        }
    }

客户端

System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();


    private void button2_Click(object sender, EventArgs e)
    {
        NetworkStream serverStream = clientSocket.GetStream();
        byte[] outStream = System.Text.Encoding.ASCII.GetBytes("Message from Client$");
        serverStream.Write(outStream, 0, outStream.Length);
        serverStream.Flush();
        int len = serverStream.ReadByte() * 256;
        len += serverStream.ReadByte();

        byte[] inStream = new byte[len];
        serverStream.Read(inStream, 0, len);
        string returndata = System.Text.Encoding.ASCII.GetString(inStream);
        msg("Data from Server : " + returndata);
    }

    private void button1_Click_1(object sender, EventArgs e)
    {
        clientSocket.Connect("127.0.0.1", 8888);
    }

2 个答案:

答案 0 :(得分:0)

此错误有几个原因,但最常见的是您写入已被另一端关闭的连接。换句话说,一个应用程序协议错误:你在一个永远无法消费的情况下写了一些东西。

如果你写两端的另一个有点遥远的可能性是你编写了客户端由于某种原因而被中止关闭。基本上你永远不应该这样做。

答案 1 :(得分:0)

我对Socket API的理解是,当您完成发送时,您应该致电Shutdown(Write)。然后,读取直到流返回0.这意味着另一方也调用了Shutdown

只有在您完全关闭写入(使用Shutdown)并且接收到零长度读取之后,才能在线路上完成通信。现在Dispose Socket现在已经不存在了。

这样,只有在发生网络错误或错误时才会出现异常。在这种情况下,您应该丢弃当前的“事务”并重新启动它。

相关问题