网上一个大佬说的,心跳连接是为了保活,大概思路是持续的向服务端发送心跳包,如果一段时间没收到回应则判定下线,但是实际测试过程中发现,这样的思路根本就不可靠,因为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))
{
//重复上线?