C#实现TCP心跳检测机制

在开发客户端程序、设备上位机软件、物联网系统时,TCP 长连接是一种非常常见的通信方式。

例如:

上位机与工业设备之间保持连接;

客户端与服务器之间实时通信;

智能硬件设备持续上传状态数据。

但是 TCP 本身只负责保证数据可靠传输,并不会主动告诉我们当前连接是否还有效。

例如:

网络突然断开;

设备异常掉电;

路由器连接中断;

对端程序崩溃;

这些情况下,TCP连接可能不会立即触发断开事件,导致应用层仍然认为连接正常。

因此,在实际项目中通常需要增加心跳检测机制(Heartbeat),通过定时发送数据包检测双方连接状态。

本文将介绍如何使用 C# 实现一个简单的 TCP 心跳检测机制,适用于客户端、服务器、设备通信等场景。

一、为什么TCP需要心跳检测

很多开发者刚接触 TCP 时,会认为:

“TCP连接成功后,只要没有异常,就一直保持连接。”

实际情况并不是这样。

TCP连接状态主要依赖操作系统维护,但是操作系统并不能实时知道网络另一端是否正常。

例如:

客户端连接设备:

Client  <-------------->  Device

        TCP Connected

此时设备突然断电:

Client  <-------------->  Device(关闭)

客户端可能仍然保持:

Socket Connected = true

但是实际上已经无法通信。

如果此时发送业务数据:

发送数据

    ↓

等待响应

    ↓

超时

会导致业务逻辑阻塞。

因此通常增加心跳:

Client              Device

  Ping  ------------>

      <------------ Pong

  Ping  ------------>

      <------------ Pong

通过固定周期通信:

判断连接是否正常;

检测设备在线状态;

及时释放异常连接;

重新建立连接。

二、设计一个简单的心跳机制

一个基础的 TCP 心跳主要包含几个部分:

心跳发送定时器

心跳消息格式

接收响应处理

超时判断

例如定义一个简单协议:

客户端发送:

{

    "type":"heartbeat",

    "time":"2026-08-11 10:00:00"

}

设备返回:

{

    "type":"heartbeat_response"

}

实际项目中可能使用:

JSON

二进制协议

自定义数据帧

例如:

AA 55 01 00 FF

根据设备协议进行定义即可。

三、C#实现TCP客户端心跳管理

首先创建一个简单的 TCP 客户端。

public class TcpClientManager

{

    private TcpClient tcpClient;

    private NetworkStream networkStream;

    public async Task ConnectAsync(string ip, int port)

    {

        tcpClient = new TcpClient();

        await tcpClient.ConnectAsync(ip, port);

        networkStream = tcpClient.GetStream();

        Console.WriteLine("TCP连接成功");

    }

}

连接成功后,可以启动心跳任务。

定义心跳间隔:

private readonly int heartbeatInterval = 5000;

private DateTime lastHeartbeatTime;

创建心跳循环:

public async Task StartHeartbeatAsync()

{

    while(true)

    {

        await SendHeartbeatAsync();

        await Task.Delay(heartbeatInterval);

    }

}

这里每5秒发送一次心跳。

四、发送心跳数据

实现发送方法:

private async Task SendHeartbeatAsync()

{

    if(networkStream == null)

    {

        return;

    }

    string message = "{\"type\":\"heartbeat\"}";

    byte[] data = Encoding.UTF8.GetBytes(message);

    await networkStream.WriteAsync(

        data,

        0,

        data.Length

    );

    lastHeartbeatTime = DateTime.Now;

    Console.WriteLine("发送心跳");

}

发送完成后,需要等待设备返回响应。

五、接收心跳响应与超时检测

启动接收线程:

public async Task ReceiveAsync()

{

    byte[] buffer = new byte[1024];

    while(true)

    {

        int length = await networkStream.ReadAsync(

            buffer,

            0,

            buffer.Length

        );

        if(length == 0)

        {

            Console.WriteLine("连接断开");

            break;

        }

        string message =

            Encoding.UTF8.GetString(

                buffer,

                0,

                length

            );

        HandleMessage(message);

    }

}

处理收到的数据:

private DateTime lastReceiveTime;

private void HandleMessage(string message)

{

    Console.WriteLine(

        $"收到数据:{message}"

    );

    if(message.Contains("heartbeat_response"))

    {

        lastReceiveTime = DateTime.Now;

        Console.WriteLine(

            "心跳响应正常"

        );

    }

}

然后增加超时检测:

private bool CheckHeartbeatTimeout()

{

    TimeSpan span =

        DateTime.Now - lastReceiveTime;

    if(span.TotalSeconds > 15)

    {

        return true;

    }

    return false;

}

例如:

5秒发送一次心跳;

15秒没有收到响应;

认为设备已经离线。

六、实际项目中的优化方向

上面的代码适合演示基本流程,实际项目中通常还需要进一步优化。

1. 心跳包不要和业务数据混合

建议定义独立消息类型:

例如:

消息类型

0x01 登录

0x02 心跳

0x03 数据上传

0x04 控制指令

收到数据后:

switch(type)

{

    case Heartbeat:

        HandleHeartbeat();

        break;

    case Data:

        HandleData();

        break;

}

这样后期扩展更加方便。

2. 增加自动重连机制

设备断开后:

检测断开

关闭Socket

等待

重新连接

恢复通信

例如:

while(!connected)

{

    try

    {

        await ConnectAsync();

    }

    catch

    {

        await Task.Delay(3000);

    }

}

3. 避免多个线程同时操作Socket

TCP通信中经常出现:

接收线程;

心跳线程;

业务发送线程。

多个线程同时Write可能导致数据混乱。

通常增加发送队列:

业务线程

Message Queue

TCP发送线程

Socket

这也是很多工业上位机程序采用的设计方式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容