C#检测TCP断开连接 [英] c# detecting tcp disconnect

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

问题描述

我有两个简单的应用程序:

I have two simple applications:


  • 一个服务器应用程序,它在特定的tcp端口上等待客户端连接。然后听他说的话,发回一些反馈并断开该客户端的连接。

  • A Server application that waits on a specific tcp port for a client to connect. Then listens to what he says, send back some feedback and DISCONNECT that client.

连接到服务器应用程序的Form应用程序,然后说一些话,然后等待以获得反馈并与服务器断开连接,然后以以下形式显示反馈。

A Form application that connects to the server application, then says something, then wait for the feedback and disconnect from the server, then show the feedback in the form.

尽管服务器应用程序似乎行为正常(我已经使用Telnet测试过,可以看到反馈,并且可以在反馈后立即看到断开连接),但是表单应用程序似乎没有注意到与服务器断开连接。 (即使服务器断开连接后,TcpClient.Connected仍然保持为真)。

Though the server application seems to behave correctly (I have tested it with Telnet and I see the feedback and I see the disconnect occurring directly after the feedback), the form application however doesn't seem to notice the disconnect from the server. ( TcpClient.Connected seems to stay true even after the server has disconnected )

我的问题是:为什么TcpClient.Connected保持为真,以及如何/何时知道服务器已断开连接?

My question is: why is TcpClient.Connected staying true and how can I know if/when the server has disconnected?

这是我的完整代码:

表单应用程序:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Sender
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void sendButton_Click(object sender, EventArgs e)
        {
            TcpClient tcpClient = new TcpClient();
            tcpClient.Connect(IPAddress.Parse("127.0.0.1"), 81);
            responseLabel.Text = "waiting for response...";
            responseLabel.Invalidate();

            // write request
            NetworkStream networkStream = tcpClient.GetStream();
            byte[] buffer = (new ASCIIEncoding()).GetBytes("Hello World! ");
            networkStream.Write(buffer, 0, buffer.Length);
            networkStream.Flush();

            // read response
            Thread readThread = new Thread(new ParameterizedThreadStart(ReadResponse));
            readThread.Start(tcpClient);
        }

        void ReadResponse(object arg)
        {
            TcpClient tcpClient = (TcpClient)arg;
            StringBuilder stringBuilder = new StringBuilder();
            NetworkStream networkStream = tcpClient.GetStream();
            bool timeout = false;
            DateTime lastActivity = DateTime.Now;
            while (tcpClient.Connected && !timeout)
            {
                if (networkStream.DataAvailable)
                {
                    lastActivity = DateTime.Now;
                    while (networkStream.DataAvailable)
                    {
                        byte[] incomingBuffer = new byte[1024];
                        networkStream.Read(incomingBuffer, 0, 1024);
                        char[] receivedChars = new char[1024];
                        (new ASCIIEncoding()).GetDecoder().GetChars(incomingBuffer, 0, 1024, receivedChars, 0);
                        stringBuilder.Append(receivedChars);
                    }
                }
                else
                {
                    if (DateTime.Now > lastActivity.AddSeconds(60))
                        timeout = true;
                }
                System.Threading.Thread.Sleep(50);
            }
            Invoke((MethodInvoker)delegate
            {
                responseLabel.Text = "Response from Listener:\n" + stringBuilder.ToString();
                responseLabel.Invalidate();
            });

            if (timeout)
            {
                Console.Write("A timeout occured\n");
                networkStream.Close();
                tcpClient.Close();
            }
        }

    }
}

服务器应用程序

using System.Net;
using System.Net.Sockets;
using System.Text;
using System;
using System.Threading;

namespace Listener
{
    class Program
    {
        static void Main(string[] args)
        {
            var tcpListener = new TcpListener(IPAddress.Any, 81);
            tcpListener.Start();
            Thread clientThread = new Thread(new ParameterizedThreadStart(Listen));
            clientThread.Start(tcpListener);
        }

        static void Listen(object arg)
        {
            TcpListener tcpListener = (TcpListener)arg;
            while (true)
            {
                TcpClient tcpClient = tcpListener.AcceptTcpClient();
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClient));
                clientThread.Start(tcpClient);
            }
        }

        static void HandleClient(object arg)
        {
            TcpClient tcpClient = (TcpClient)arg;
            StringBuilder stringBuilder = new StringBuilder();
            ASCIIEncoding encoder = new ASCIIEncoding();
            DateTime lastActivity = DateTime.Now;

            // read request
            NetworkStream networkStream = tcpClient.GetStream();
            int timeout = 5; // gives client some time to send data after connecting
            while (DateTime.Now < lastActivity.AddSeconds(timeout) && stringBuilder.Length==0)
            {
                if (!networkStream.DataAvailable)
                {
                    System.Threading.Thread.Sleep(50);
                }
                else
                {
                    while (networkStream.DataAvailable)
                    {
                        lastActivity = DateTime.Now;
                        byte[] incomingBuffer = new byte[1024];
                        networkStream.Read(incomingBuffer, 0, 1024);
                        char[] receivedChars = new char[1024];
                        encoder.GetDecoder().GetChars(incomingBuffer, 0, 1024, receivedChars, 0);
                        stringBuilder.Append(receivedChars);
                    }
                }
            }
            string request = stringBuilder.ToString();

            // write response
            string response = "The listener just received: " + request;
            byte[] outgoingBuffer = encoder.GetBytes(response);
            networkStream.Write(outgoingBuffer, 0, outgoingBuffer.Length);
            networkStream.Flush();

            networkStream.Close();
            tcpClient.Close();
        }
    }

}


推荐答案

关闭连接时,不会收到TcpClient / NetworkStream的通知。
唯一可用的选择是在写入流时捕获异常。

TcpClient / NetworkStream does not get notified when the connection is closed. The only option available to you is to catch exceptions when writing to the stream.

几年前,我们开始使用套接字而不是tcp客户端。与tcpclient相比,套接字更有用。

A few years back we moved to using sockets instead of tcp client. socket is more usable as compared to tcpclient.

有两种方法可以使用

投票是其中之一

http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.poll.aspx

您还可以检查Write本身的结果。它为您提供实际写入的字节数。

You can also do a check on outcome of Write itself. it gives you the number of bytes actually written.

Connected属性本身仅反映上一次操作的状态。它的文档指出: Connected属性的值反映了最近操作的连接状态。如果需要确定连接的当前状态,请进行无阻塞,零字节的Send调用。如果调用成功返回或抛出WAEWOULDBLOCK错误代码(10035),则套接字仍已连接;否则,套接字不再连接。

The Connected property itself only reflects the state at the last operation. Its documentation states "The value of the Connected property reflects the state of the connection as of the most recent operation. If you need to determine the current state of the connection, make a non-blocking, zero-byte Send call. If the call returns successfully or throws a WAEWOULDBLOCK error code (10035), then the socket is still connected; otherwise, the socket is no longer connected."

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

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

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