UN2L7——实现心跳消息
UN2L7——实现心跳消息
心跳消息
所谓心跳消息,就是在长连接中,客户端和服务端之间定期发送的一种特殊的数据包,用于通知对方自己还在线,以确保长连接的有效性
由于其发送的时间间隔往往是固定的持续的,就像是心跳一样一直存在,所以我们称之为心跳消息
心跳消息是长连接项目中必备的一套逻辑规则,通过它可以帮助我们在服务器端及时的释放掉失效的socket
可以有效避免当客户端非正常关闭时,服务器端不能及时判断连接已断开
为什么需要心跳消息
- 避免非正常关闭客户端时,服务器无法正常收到关闭连接消息,通过心跳消息我们可以自定义超时判断,
如果超时没有收到客户端消息,证明客户端已经断开连接 - 避免客户端长期不发送消息,防火墙或者路由器会断开连接,我们可以通过心跳消息一直保持活跃状态
实现心跳消息
首先声明一个不包括消息体的心跳消息
1 | public class HeartMessage : BaseMessage |
-
客户端,主要功能:定时发送消息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//客户端 NetManager类内部
private HeartMessage heartMsg = new HeartMessage();
private void Awake()
{
instance = this;
DontDestroyOnLoad(gameObject);
InvokeRepeating(nameof(SendHeartMsg), 0, SEND_HEART_MSG_TIME); //客户端循环定时给服务端发送心跳消息
}
private void SendHeartMsg()
{
if (isConnented)
Send(heartMsg);
} -
服务器,主要功能:不停检测上次收到某客户端消息的时间,如果超时则认为连接已经断开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40//服务器端 ClientSocket类内部
//超时时间
private static int TIME_OUT_TIME = 10;
public void Receive()
{
if (!Connented)
{
Program.socket.AddDelSocket(this);
return;
}
try
{
if (socket.Available > 0)
{
byte[] result = new byte[1024 * 5];
int receiveNum = socket.Receive(result);
HandleReceiveMsg(result, receiveNum);
}
//间隔一段时间,检测一次超时,如果超时,就主动断开该客户端的连接
CheckTimeOut();
}
catch (Exception e)
{
Console.WriteLine($"从客户端{clientID}接收消息失败:{e.Message}");
//如果解析错误,也认为要把这个socket断开
Program.socket.AddDelSocket(this);
}
}
//间隔一段时间,检测一次超时,如果超时,就主动断开该客户端的连接
private void CheckTimeOut()
{
//如果接收到心跳消息的时间超过了超时时间,就断开连接
if (frontTime != -1
&& DateTime.Now.Ticks / TimeSpan.TicksPerSecond - frontTime >= TIME_OUT_TIME)
{
Program.socket.AddDelSocket(this);
}
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 文KRIFE齐的博客!