c#心跳连接

心跳连接常用于保持服务端与客户端的连接活跃。然而,实践中通过不断发送心跳包来检测连接状态的方法并不可靠,因为Socket的阻塞方式可能导致异常。在.NET开发中,当服务端意外断开时,需要使用NetworkStream.Read或Write来获取Socket的真实状态;而客户端意外关闭时,服务端通常会捕获到'远程主机关闭了一个现有连接'的异常。NetworkStream.Read是阻塞的,直到读取到数据,TcpListener.AcceptSocket()同样为阻塞方法。
摘要由CSDN通过智能技术生成

网上一个大佬说的,心跳连接是为了保活,大概思路是持续的向服务端发送心跳包,如果一段时间没收到回应则判定下线,但是实际测试过程中发现,这样的思路根本就不可靠,因为socket很多方法是阻塞式的,而且如果一旦连接断开,接收或者发送都会发生异常,有了异常捕捉就很容易判断是不是下线了,根本没必要那么复杂:(反正.net是这样)

TIPS:

1,socket建立的连接,此时如果服务端意外断开,socket还在维护中,必须要用networkstream.read或者write一次才可以得到socket正确状态
2,而如果意外关掉客户端,由于服务端始终处于读取状态,所以会报”远程主机关闭了一个现有连接“的错误
3,networkstream.read是阻塞方法,直到读到数据,没有发现读到空数据的情况
4,TcpListener.AcceptSocket()也是阻塞方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HServer
{
    static class HEARTTOOL
    {
        #region Server心跳

        /// <summary>
        /// 服务端
        /// </summary>
        public static class heartBeatServer
        {// 客户端离线委托
            public delegate void ClientOfflineHandler(ClientInfo cl);
            // 客户端上线委托
            public delegate void ClientOnlineHandler(ClientInfo cl);
            public static event ClientOfflineHandler OnClientOffline;
            public static event ClientOnlineHandler OnClientOnline;
            public static int heartPort;
            private static TcpListener Lis;
            public static int timeout;//超时时间
            //DIC:id,clientinfo
            public static Dictionary<EndPoint, ClientInfo> _DicClient = new Dictionary<EndPoint, ClientInfo>();
            private static Thread t2;
            /// <summary>
            /// 开启服务端
            /// </summary>
            public static void Start()
            {
                t2 = new Thread(new ThreadStart(ListenClientBeat));
                t2.IsBackground = true;
                t2.Start();
            }

            /// <summary>
            /// 接收心跳包
            /// </summary>
            /// <param name="clientID">客户端ID</param>
            public static void ListenClientBeat()
            {
                Socket tempSocket = null;
                IPEndPoint IPP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), heartPort);
                Lis = new TcpListener(IPP);
                try
                {
                    Lis.Start();
                    while (true)
                    {
                        tempSocket = Lis.AcceptSocket();//建立新连接,阻塞方法
                        EndPoint ep = tempSocket.RemoteEndPoint;
                        Console.WriteLine(ep.ToString());
                        if (_DicClient.ContainsKey(ep))
                        {
                            //重复上线?
  
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值