C# 远程 TCP 连接 [英] C# while remote TCP connection

查看:28
本文介绍了C# 远程 TCP 连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让服务器允许 TCP 连接并回显正在发送的任何换行符分隔的消息.我希望多个客户端能够一个接一个地连接,维护相同的服务器套接字.这是我的代码:

I am trying to have a server allow TCP connections and and echo out any newline delimited messages being sent. I want multiple clients to be able to connect one after another, maintaining the same server socket. Here's my code:

TcpClient client;

while (true) {
    Console.Write("Waiting for connection... ");
    client = listener.AcceptTcpListener();
    nStream = client.GetStream();
    sReader = new StreamReader(nStream);
    Console.WriteLine("Connected!");

    while (client.Connected) {
        string line = sReader.ReadLine();
        Console.WriteLine(line);
    }
    Console.WriteLine("#Client Disconnected")
}

不幸的是,当远程客户端断开连接时,它永远无法逃脱while (client.Connected)"循环.相反,我得到了对 STDOUT 的无限写入.

Unfortunately, when the remote client disconnects, it never escapes the "while (client.Connected)" loop. Instead I get an infinite write to STDOUT.

推荐答案

基本上,您使用的属性 TcpClient.Connection 并没有像您想象的那样发挥作用.来自 MSDN 文档:

Basically, the property that you're using TcpClient.Connection does not do what you think it does. From the MSDN documentation:

http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.connected.aspx

因为 Connected 属性只反映最近操作时的连接状态,所以您应该尝试发送或接收消息以确定当前状态.消息发送失败后,此属性不再返回 true.请注意,此行为是设计使然.您无法可靠地测试连接状态,因为在测试和发送/接收之间的时间内,连接可能已丢失.

Because the Connected property only reflects the state of the connection as of the most recent operation, you should attempt to send or receive a message to determine the current state. After the message send fails, this property no longer returns true. Note that this behavior is by design. You cannot reliably test the state of the connection because, in the time between the test and a send/receive, the connection could have been lost.

要点是在主机断开连接后但在您的服务器阻止等待从流中读取另一行之前,属性 TcpClient.Connection 没有更新.在阻止之前,您需要一种更可靠的方法来检测连接是否处于活动状态.

The gist is that the property TcpClient.Connection was not updated after the host disconnected but before your server blocked waiting to read another line from the stream. You need a more reliable way to detect if the connection is active before you block.

原来,这个问题以前有人问过.因此,我从这里借用了答案,并将其调整为您在 OP 中使用的格式.

Turns out, this question has been asked before. So, I borrowed the answer from here and adapted it to the format that you're using in the OP.

https://stackoverflow.com/a/8631090

    static void Main(string[] args)
    {
        TcpClient client = new TcpClient();
        TcpListener listener = new TcpListener(IPAddress.Loopback, 60123);
        listener.Start();

        while (true)
        {
            Console.WriteLine("Waiting for connection...");
            client = listener.AcceptTcpClient();
            Console.WriteLine("Connection found");
            StreamReader reader = new StreamReader(client.GetStream());

            string line = string.Empty;
            while (TestConnection(client))
            {
                line = reader.ReadLine();
                Console.WriteLine(line);
            }
            Console.WriteLine("Disconnected");
        }
    }

    private static bool TestConnection(TcpClient client)
    {
        bool sConnected = true;

        if (client.Client.Poll(0, SelectMode.SelectRead))
        {
            if (!client.Connected) sConnected = false;
            else
            {
                byte[] b = new byte[1];
                try
                {
                    if (client.Client.Receive(b, SocketFlags.Peek) == 0)
                    {
                        // Client disconnected
                        sConnected = false;
                    }
                }
                catch { sConnected = false; }
            }
        }
        return sConnected;
    }

当我测试它时,这对我有用,它起作用的原因是您无法判断连接是否关闭,直到您尝试从中读取或写入.您可以通过盲目尝试读/写然后处理套接字关闭时出现的 IO 异常来实现,或者您可以执行此测试器方法正在执行的操作并查看连接是否已关闭.

This works for me when I test it, and the reason that it works is that you cannot tell if the connection is closed until you attempt to read or write from it. You can do that by blindly trying to read/write and then handling the IO exceptions that come when the socket is closed, or you can do what this tester method is doing and peek to see if the connection is closed.

希望对你有帮助

编辑:

需要注意的是,这可能是也可能不是检查连接是否关闭的最有效方法,但纯粹是为了说明您必须在服务器端通过读/写而不是依赖的方式自己检查连接在 TcpClient.Connection 上.

It should be noted that this may or may not be the most efficient way to check if the connection is closed, but it is purely to illustrate that you must check the connection yourself on the server side by reading/writing instead of relying on TcpClient.Connection.

编辑 2:

我的样本没有很好地清理旧资源,向任何有强迫症反应的人道歉.

My sample doesn't clean up old resources very well, apologies to anyone who had an OCD reaction.

这篇关于C# 远程 TCP 连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆