首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TcpClient -现有连接被远程主机强制关闭。

TcpClient -现有连接被远程主机强制关闭。
EN

Stack Overflow用户
提问于 2014-07-15 20:05:06
回答 2查看 52.5K关注 0票数 5

The Info

我一直在c#中开发一个web http服务器,并决定添加一个远程控制台功能。控制台可以从任何位置使用,并使用TcpListener (web服务器)和TcpClient (远程控制台)发送命令和函数。

代码

这就是我的服务器的样子:

代码语言:javascript
运行
复制
TcpListener consoleListener = new TcpListener(consolePort);
consoleListener.Start();
byte[] bytes = new Byte[256];
string data = null;
while (true)
{
    TcpClient client = consoleListener.AcceptTcpClient();
    data = null;
    byte[] msg = { 0 };
    int i;
    while ((i = client.GetStream().Read(bytes, 0, bytes.Length)) != 0)
    {
        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
        if (data == "shutdown")
        {
            //Server shutdown logic.
        }
        //Other commands here...
        else
        {
            msg = Encoding.ASCII.GetBytes("Invalid command. Type 'help' or '?' to get a list of commands.");
        }
        client.GetStream().Write(msg, 0, msg.Length); //sends return message to console
    }
    client.Close(); //closes connection between client and server after EVERY command. Connection is reopened when a new command is sent.
}

注意-服务器在一个单独的线程上运行,同时运行到webserver和主控制台应用程序线程。

这是我的客户:

代码语言:javascript
运行
复制
public static string Communicate(string text)
{
    try
    {
        TcpClient client = new TcpClient(ip, port); //initializes tcpclient (ip and port are correct)

        byte[] data = System.Text.Encoding.ASCII.GetBytes(text); //converts text to bytes for stream writing

        NetworkStream stream = client.GetStream();

        stream.Write(data, 0, data.Length);

        Console.WriteLine("Sent data: " + text);

        data = new Byte[256];

        string responseData = String.Empty; //initializes responsData string

        Int32 bytes = stream.Read(data, 0, data.Length);
        responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
        client.Close();
        return responseData; //returns what server writes
    }
    catch (Exception ex)
    {
        return "An error occured\n" + ex.ToString();
    }
}

问题

我可以向服务器发送一个命令,并成功返回。但是,当我尝试发送另一个命令时,服务器会抛出以下错误:

代码语言:javascript
运行
复制
System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at ---.Server.ConsoleListener() in X:\Users\---\Documents\Visual Studio 2013\Projects\---\---\Program.cs:line x

我知道这不是防火墙或管理员提升问题,因为我可以成功地发送一个命令。只有在发送的第二个命令中,它才会抛出此错误。

下面是一个描述问题的屏幕截图:

编辑:通过做一些研究,我发现这个问题很可能是我的for循环中的一个小错误造成的。但是,我不知道如何解决这个问题,因为我不知道确切的问题:)。请帮我确认一下,这样我就能修好它了。

再次感谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-15 20:29:18

似乎您的客户在一条消息之后关闭了连接。

代码语言:javascript
运行
复制
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
client.Close();
return responseData; //returns what server writes

如果您想要持久化连接,您应该在客户机上有一个类似于服务器上的循环。如果您想每次建立一个新的连接,您应该在服务器上优雅地关闭流,而不是像这样有一个循环。如果消息较长,或者需要为命令指定最大长度,则仍然需要循环。

票数 5
EN

Stack Overflow用户

发布于 2019-01-09 03:40:48

我也有同样的解决方案。如果客户端断开连接,通常会发生这种情况。不幸的是,Alex的解决方案不起作用。你会得到另一个例外。最佳解决方案由Microsoft描述为这里

您需要使用CanRead进行检查

代码语言:javascript
运行
复制
TcpClient tcpClient = new TcpClient ();

// Uses the GetStream public method to return the NetworkStream.
NetworkStream netStream = tcpClient.GetStream ();

if (netStream.CanRead)
{
    // Reads NetworkStream into a byte buffer.
    byte[] bytes = new byte[tcpClient.ReceiveBufferSize];

    // Read can return anything from 0 to numBytesToRead. 
    // This method blocks until at least one byte is read.
    netStream.Read (bytes, 0, (int)tcpClient.ReceiveBufferSize);

    // Returns the data received from the host to the console.
    string returndata = Encoding.UTF8.GetString (bytes);

    Console.WriteLine ("This is what the host returned to you: " + returndata);

}
else
{
    Console.WriteLine ("You cannot read data from this stream.");
    tcpClient.Close ();

    // Closing the tcpClient instance does not close the network stream.
    netStream.Close ();
    return;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24767184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档