如何测试连接后的TcpClient的连接断开? [英] How to test for a broken connection of TCPClient after being connected?

查看:483
本文介绍了如何测试连接后的TcpClient的连接断开?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在一个问题争抢一个运动3天,我找不到任何解决办法,请帮助:)结果
我用Visual Studio 2010和C#语言的工作。

I've been fighting with one problem for a whole 3 days I can't find any solution, please help :)
I work with Visual Studio 2010 and C# language.

我有一个设备那样工作的服务器,在时间(无法定义任何读超时)非常月经不调发送一些数据。结果
我写了一个TCP客户端连接到服务器和读取数据。它的工作原理确定,但是当事情是错误的网络和服务器不可用(例如,当我从我的电脑拔掉网线),大约需要10秒的应用程序通知没有对服务器和罚球没有连接一个例外。 (我不知道为什么整整10 seconds其中它的定义我可以改变它??)结果
我想更快的反应 - 让说后连接断结果
后一秒然而,谷歌搜索答案不提供我任何可行的解决方案。

I have a device working like a server, that sends some data in a very irregular periods of time (not possible to define any read timeout).
I wrote a TCP client to connect to that server and read data. It works OK, however when something is wrong with the network and server becomes unavailable (e.g. when I plug out the network cable from my computer), it takes about 10 seconds for application to "notice" there is no connection to the server and throw an exception. (I don't know why exactly 10 seconds? Where it's defined? Can I change it?)
I want to react faster - let say after one second after connection broken.
Googling for answer however doesn't provide me any working solution.

测试代码如下,我尽量做到2线程:一个是读取数据,第二个是寻找连接状态,并应报警我,当它坏。它不工作既不的TcpClient也不Socket类。我试着读/写一些数据 tcpClient.SendTimeout = 100; stream.WriteTimeout = 100; 。但它似乎并没有工作。

The test code is below, I try to make it on 2 threads: one is reading data, the second one is looking for connection status and should alarm me when it's broken. It's not working neither for TCPClient nor Socket class. I've tried to read / write some data with tcpClient.SendTimeout = 100; and stream.WriteTimeout = 100; but it doesn't seem to work.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;

namespace TCPClient
{
    class Program
    {
        static volatile bool _continue = true;
        static TcpClient tcpClient;
        static NetworkStream stream;

        static void Main(string[] args)
        {
            try
            {
                //client thread - listen from server
                Thread tcpListenThread = new Thread(TcpListenThread);
                tcpListenThread.Start();

                //connection checking thread
                Thread keepAliveThread = new Thread(KeepAliveThread);
                keepAliveThread.Start();

                while (_continue)
                {
                    if (Console.ReadLine() == "q")
                    {
                        _continue = false;
                    }
                }

                keepAliveThread.Join(2000);
                if (keepAliveThread.IsAlive)
                {
                    Console.WriteLine("Thread keepAlive has been aborted...");
                    keepAliveThread.Abort();
                }

                tcpListenThread.Join(2000);
                if (tcpListenThread.IsAlive)
                {
                    Console.WriteLine("Listen thread has been aborted...");
                    tcpListenThread.Abort();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("\n" + ex.Message);
            }

            Console.WriteLine("\nHit any key to quit...");
            Console.Read();
        }

        private static void TcpListenThread()
        {
            string server = "172.20.30.40";
            int port = 3000;

            try
            {
                using (tcpClient = new TcpClient())
                {
                    tcpClient.Connect(server, port);

                    if (tcpClient.Connected)
                        Console.WriteLine("Successfully connected to server");

                    using (stream = tcpClient.GetStream())
                    {

                        while (_continue)
                        {
                            Byte[] data = new Byte[1024];
                            Int32 bytes = stream.Read(data, 0, data.Length);
                            string responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);

                            Console.WriteLine("Received: {0}, responseData);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Listen thread exception! " + ex.Message);
            }
        }


        private static void KeepAliveThread()
        {
            while (_continue)
            {
                if (tcpClient != null)
                {
                    try
                    {
                        //...what to put here to check or throw exception when server is not available??...
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Disconnected...");
                    }
                }

                Thread.Sleep(1000);  //test for connection every 1000ms
            }
        }
    }
}

编辑:结果
@卡斯滕的回答是:虽然它看起来很有希望,此解决方案不工作......结果
我做了最简单的测试应用程序:


@carsten's answer: although it looks promising, this solution do not work...
I made the simplest test application for that:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;

namespace TCPClientTest
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string server = "172.20.30.40";
                int port = 3000;

                using (TcpClient tcpClient = new TcpClient())
                {
                    tcpClient.Connect(server, port);

                    int i = 0;
                    while (true)
                    {
                        // This is how you can determine whether a socket is still connected.
                        bool blockingState = tcpClient.Client.Blocking;
                        try
                        {
                            byte[] tmp = new byte[1];

                            tcpClient.Client.Blocking = false;
                            tcpClient.Client.Send(tmp, 0, 0);
                            Console.WriteLine("Connected!");
                        }
                        catch (SocketException e)
                        {
                            // 10035 == WSAEWOULDBLOCK
                            if (e.NativeErrorCode.Equals(10035))
                                Console.WriteLine("Still Connected, but the Send would block");
                            else
                            {
                                Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
                            }
                        }
                        finally
                        {
                            tcpClient.Client.Blocking = blockingState;
                        }

                        Console.WriteLine("Connected: {0} ({1})", tcpClient.Client.Connected, i++);

                        Thread.Sleep(1000);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Global exception: {0}", ex.Message);
            }
        }
    }
}



结果如下,它显示:

The results are following, it displays:

连接的结果
连接:真

再加上我的订单号每隔一秒。当我拔下网线,它需要8秒钟才开始打印:

plus my order number every one second. When I disconnect network cable, it takes 8 seconds to start printing:

Disonnected:错误代码10054结果
连接:假

因此通过8秒我不知道该连接丢失。它看起来像ping命令是最好的选择在这里,但我会测试其他的解决方案。

so by 8 seconds I'm not aware that the connection is lost. It looks like pinging is the best option here, yet I'll test another solutions.

推荐答案

简单的答案。你不能。 TCP是在某种程度上不允许本作。但是,正常的方式实现这一目标是发送Ping与邮件相比较短的时间间隔。所以,说,每当你从服务器的消息,则启动倒计时1分钟的时钟,然后你发送一个ping命令(如果你还没有收到之间一个新的消息)。如果您没有收到你的平在30秒内响应,你的结论是连接中断。

Simple answer. You can't. Tcp is made in a way which doesn't allow this. However, the normal way to achieve this is to send ping's with shorter interval than messages. So, say, that whenever you get a message from the server, you start a clock that count down 1 min, then you send a "ping" command (if you haven't received a new message in between). If you don't receive a response to your "ping" within 30 seconds, you conclude that the connection is broken.

从理论上讲,你应该能够在做到这一点一个包级(TCP发送ACK,你应该能够检查),但我不知道这是否在C#中是可能的,或任何编程语言,对于这个问题,或者你需要做的,在固件/硬件。

Theoretically, you should be able to do this on a package-level (tcp sends ACK which you should be able to check for), but I don't know if that's possible in C#, or any programming language for that matter, or if you need to do that in firmware/hardware.

这篇关于如何测试连接后的TcpClient的连接断开?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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