我是靠谱客的博主 精明冰淇淋,最近开发中收集的这篇文章主要介绍使用“带外数据”实现TCP心跳包 使用“带外数据”实现TCP心跳包,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 

使用“带外数据”实现TCP心跳包

标签: 带外数据网络心跳包
  2398人阅读  评论(2)  收藏  举报
  分类:
 

    公司有一个基于TCP的IM项目,开发人员将心跳包与数据流混在了一起,从而增加了数据提取的难度和出错的机率,我提出使用带外数据来实现心跳包,该开发人员认为这是一种过时的不被.NET支持的技术特性,其实.NET不是空中楼阁,他的所有技术都是基于原来WIN32技术的基础之上的,只不过增强了OO特性而已,为验证自己的想法,因此花费了几个小时编写了使用“带外数据”实现TCP心跳包的DEMO类,并成功通过测试。

    该DEMO类分别对应SOCKET通讯的SERVER端和CLIENT端进行了不同处理,两端的心跳时间间隔最好设为一致,否则可能导致结果错误,此外,由于心跳包是定时异步执行的,在开发期间如果有暂停运行的调试需要,最好将心跳包功能暂时关闭,以免因心跳包发送或接收超时而抛出错误。

    一、心跳包代码如下:

[vb]  view plain  copy
  1. '* *************************************************************** *  
  2. '*   模块名称:NetHeartbeat.vb  
  3. '*   功能描述:心跳包处理类  
  4. '*   作者:lyserver  
  5. '*   编码日期:2011年11月14日  
  6. '*   修改日期:  
  7. '* *************************************************************** *  
  8.   
  9. Imports System.Net.Sockets  
  10.   
  11. ''' <summary>  
  12. ''' 心跳包处理类  
  13. ''' </summary>  
  14. Public Class NetHeartbeat  
  15.     Implements IDisposable  
  16.   
  17.     ''' <summary>  
  18.     ''' 心跳包处理方式(发送或接收)  
  19.     ''' </summary>  
  20.     Public Enum MethodConstants  
  21.         [Send] = 0  
  22.         [Recv] = 1  
  23.     End Enum  
  24.   
  25.     ''' <summary>  
  26.     ''' 心跳包描述类  
  27.     ''' </summary>  
  28.     Private Class HeartbeatInfo '心跳包信息  
  29.         Public Buffer As Byte() = New Byte(0) {} '心跳包数据缓冲区  
  30.         Public Times As Integer = 0 '心跳包检测次数  
  31.         Public Success As Boolean = True '心跳包发送或接收成功标志  
  32.     End Class  
  33.   
  34.     Private m_Socket As Socket = Nothing '套接字  
  35.     Private WithEvents m_Timer As Timers.Timer = New Timers.Timer(1000) '定时器  
  36.     Private m_HeartbeatInfo As HeartbeatInfo = Nothing '心跳包描述对象  
  37.     Private m_Method As MethodConstants = MethodConstants.Send '心跳包处理方式  
  38.     Private m_TryTimes As UInteger = 5 '心跳包出错后的最大尝试次数  
  39.   
  40.     Public Delegate Sub MyEventHandler(ByVal sender As NetHeartbeat, ByVal message As String)  
  41.     Public Event OnError As MyEventHandler  
  42.   
  43.     Public Sub New()  
  44.     End Sub  
  45.   
  46.     Public Sub New(ByVal sock As Socket)  
  47.         m_Socket = sock  
  48.     End Sub  
  49.     Public Sub New(ByVal sock As Socket, ByVal method As MethodConstants)  
  50.         m_Socket = sock  
  51.         m_Method = method  
  52.     End Sub  
  53.     Public Sub New(ByVal sock As Socket, ByVal method As MethodConstants, ByVal enabled As Boolean)  
  54.         m_Socket = sock  
  55.         m_Method = method  
  56.         Me.Enabled = enabled  
  57.     End Sub  
  58.     Public Sub New(ByVal sock As Socket, ByVal method As MethodConstants, ByVal enabled As BooleanByVal interval As Integer)  
  59.         m_Socket = sock  
  60.         m_Method = method  
  61.         Me.Enabled = enabled  
  62.         Me.Interval = interval  
  63.     End Sub  
  64.   
  65.     ''' <summary>  
  66.     ''' 重置心跳包处理状态  
  67.     ''' </summary>  
  68.     Public Sub Reset()  
  69.         If m_HeartbeatInfo Is Nothing Then  
  70.             m_HeartbeatInfo = New HeartbeatInfo()  
  71.         End If  
  72.         m_HeartbeatInfo.Times = 0  
  73.         m_HeartbeatInfo.Success = True  
  74.     End Sub  
  75.   
  76.     ''' <summary>  
  77.     ''' 绑定套接字,并指定心跳包处理方式  
  78.     ''' </summary>  
  79.     Public Sub Bind(ByVal sock As Socket, ByVal method As MethodConstants)  
  80.         m_Socket = sock  
  81.         m_Method = method  
  82.     End Sub  
  83.   
  84.     ''' <summary>  
  85.     ''' 启动或停止心跳包  
  86.     ''' </summary>  
  87.     Public Property Enabled() As Boolean  
  88.         Get  
  89.             Return m_Timer.Enabled  
  90.         End Get  
  91.         Set(ByVal value As Boolean)  
  92.             Reset()  
  93.             m_Timer.Enabled = value  
  94.         End Set  
  95.     End Property  
  96.   
  97.     ''' <summary>  
  98.     ''' 心跳包处理间隔时间(毫秒)  
  99.     ''' </summary>  
  100.     Public Property Interval() As UInteger  
  101.         Get  
  102.             Return m_Timer.Interval  
  103.         End Get  
  104.         Set(ByVal value As UInteger)  
  105.             m_Timer.Interval = value  
  106.         End Set  
  107.     End Property  
  108.   
  109.     ''' <summary>  
  110.     ''' 心跳包接收或发送时出错、超时、失败后重试次数  
  111.     ''' </summary>  
  112.     Public Property TryTimes() As UInteger  
  113.         Get  
  114.             Return m_TryTimes  
  115.         End Get  
  116.         Set(ByVal value As UInteger)  
  117.             m_TryTimes = value  
  118.         End Set  
  119.     End Property  
  120.   
  121.     ''' <summary>  
  122.     ''' 心跳包处理方式:接收或发送  
  123.     ''' </summary>  
  124.     Public Property Method() As MethodConstants  
  125.         Get  
  126.             Return m_Method  
  127.         End Get  
  128.         Set(ByVal value As MethodConstants)  
  129.             m_Method = value  
  130.         End Set  
  131.     End Property  
  132.   
  133.     ''' <summary>  
  134.     ''' 发送心跳包  
  135.     ''' </summary>  
  136.     Private Sub SendHeartbeat()  
  137.         Try  
  138.             If m_HeartbeatInfo.Success = True Then '如果上一次发送动作已成功,则继续发送心跳包  
  139.                 m_HeartbeatInfo.Success = False  
  140.                 m_Socket.BeginSend(m_HeartbeatInfo.Buffer, 0, 1, SocketFlags.OutOfBand, AddressOf Me.EndSendOOB, Nothing)  
  141.             Else '否则,超时计数器加1  
  142.                 m_TryTimes += 1  
  143.             End If  
  144.         Catch ex As Exception  
  145.             ErrorHandler(ex.Message)  
  146.         End Try  
  147.     End Sub  
  148.     Private Sub EndSendOOB(ByVal ar As IAsyncResult)  
  149.         Try  
  150.             Dim nSendCount As Integer = m_Socket.EndSend(ar)  
  151.             m_HeartbeatInfo.Success = True '设置心跳包发送成功标志  
  152.             m_TryTimes = 0 '超时计数器归0  
  153.         Catch ex As Exception  
  154.             ErrorHandler(ex.Message)  
  155.         End Try  
  156.     End Sub  
  157.   
  158.     ''' <summary>  
  159.     ''' 接收心跳包  
  160.     ''' </summary>  
  161.     Private Sub RecvHeartbeat()  
  162.         Try  
  163.             If m_HeartbeatInfo.Success = True Then '如果上一次接收动作已成功,则继续接收心跳包  
  164.                 m_HeartbeatInfo.Success = False  
  165.                 m_Socket.BeginReceive(m_HeartbeatInfo.Buffer, 0, 1, SocketFlags.OutOfBand, AddressOf Me.EndRecvOOB, Nothing)  
  166.             Else '否则,超时计数器加1  
  167.                 m_TryTimes += 1  
  168.             End If  
  169.         Catch ex As Exception  
  170.             ErrorHandler(ex.Message)  
  171.         End Try  
  172.     End Sub  
  173.     Private Sub EndRecvOOB(ByVal ar As IAsyncResult)  
  174.         Try  
  175.             Dim nRecvCount As Integer = m_Socket.EndReceive(ar)  
  176.             m_HeartbeatInfo.Success = True '设置心跳包接收成功标志  
  177.             m_TryTimes = 0 '超时计数器归0  
  178.         Catch ex As Exception  
  179.             ErrorHandler(ex.Message)  
  180.         End Try  
  181.     End Sub  
  182.   
  183.     ''' <summary>  
  184.     ''' 定时检查心跳包发送或接收情况,并根据结果判断是否继续发送或接收心跳包,或者抛出心跳包处理异常  
  185.     ''' </summary>  
  186.     Private Sub m_Timer_Elapsed(ByVal sender As ObjectByVal e As System.Timers.ElapsedEventArgs) Handles m_Timer.Elapsed  
  187.         If m_HeartbeatInfo Is Nothing Then  
  188.             m_Timer.Enabled = False  
  189.             Exit Sub  
  190.         End If  
  191.         Try  
  192.             If m_Method = MethodConstants.Send Then '如果心跳包处理方式为发送  
  193.                 If m_HeartbeatInfo.Success = True Then '如果心跳包已发送成功,则继续发送  
  194.                     SendHeartbeat()  
  195.   
  196.                     Console.WriteLine("心跳包发送成功")  
  197.   
  198.                 Else '否则,心跳包发送超时或出错  
  199.                     If m_HeartbeatInfo.Times < m_TryTimes Then '如果超时或出错次数小于指定的次数,则继续发送  
  200.                         SendHeartbeat()  
  201.                     Else '否则,抛出心跳包发送异常错误  
  202.                         ErrorHandler("心跳包发送超时")  
  203.                     End If  
  204.                 End If  
  205.             Else '如果心跳包处理方式为接收   
  206.                 If m_HeartbeatInfo.Success = True Then '如果心跳包已接收成功,则继续接收  
  207.                     RecvHeartbeat()  
  208.   
  209.                     Console.WriteLine("心跳包接收成功")  
  210.                 Else '否则,心跳包接收超时或出错  
  211.                     If m_HeartbeatInfo.Times < m_TryTimes Then '如果超时或出错次数小于指定的次数,则继续接收  
  212.                         RecvHeartbeat()  
  213.                     Else '否则,抛出心跳包接收异常错误  
  214.                         ErrorHandler("心跳包接收超时")  
  215.                     End If  
  216.                 End If  
  217.             End If  
  218.         Catch ex As Exception  
  219.             ErrorHandler(ex.Message)  
  220.         End Try  
  221.     End Sub  
  222.   
  223.     ''' <summary>  
  224.     ''' 异常处理  
  225.     ''' </summary>  
  226.     Private Sub ErrorHandler(ByVal message As String)  
  227.         Try  
  228.             m_Timer.Enabled = False  
  229.             If m_HeartbeatInfo IsNot Nothing Then  
  230.                 m_HeartbeatInfo.Times = m_TryTimes  
  231.                 m_HeartbeatInfo.Success = False  
  232.             End If  
  233.         Catch ex As Exception  
  234.         End Try  
  235.         RaiseEvent OnError(Me, message)  
  236.     End Sub  
  237.   
  238.     Private disposedValue As Boolean = False        ' 检测冗余的调用  
  239.   
  240.     ' IDisposable  
  241.     Protected Overridable Sub Dispose(ByVal disposing As Boolean)  
  242.         If Not Me.disposedValue Then  
  243.             If disposing Then  
  244.                 ' TODO: 显式调用时释放非托管资源  
  245.             End If  
  246.   
  247.             ' TODO: 释放共享的非托管资源  
  248.             m_Timer.Enabled = False  
  249.             m_Socket = Nothing  
  250.             m_HeartbeatInfo = Nothing  
  251.         End If  
  252.         Me.disposedValue = True  
  253.     End Sub  
  254.  
  255. #Region " IDisposable Support "  
  256.     ' Visual Basic 添加此代码是为了正确实现可处置模式。  
  257.     Public Sub Dispose() Implements IDisposable.Dispose  
  258.         ' 不要更改此代码。请将清理代码放入上面的 Dispose(ByVal disposing As Boolean) 中。  
  259.         Dispose(True)  
  260.         GC.SuppressFinalize(Me)  
  261.     End Sub  
  262. #End Region  
  263.   
  264. End Class  

 

    二、类使用说明:

    1、如果要处理心跳包事件,请使用Private WithEvents m_Heartbeat As NetHeartbeat = New NetHeartbeat 来实例化心跳包。

    2、如果要修改心跳包处理方式,请使用Heartbeat .Bind(sock,MethodConstants.Recv)方法来指定心跳包的处理套接字和处理方式,建议最好由客户端发送心跳包,服务器端接收心跳包。

    3、如果要修改心跳包处理的时间间隔,请修改m_Heartbeat的Interval属性,该时间间隔的单位为毫秒。

    4、如果要启动心跳包,请设置m_Heartbeat的Enabled属性为True。

最后

以上就是精明冰淇淋为你收集整理的使用“带外数据”实现TCP心跳包 使用“带外数据”实现TCP心跳包的全部内容,希望文章能够帮你解决使用“带外数据”实现TCP心跳包 使用“带外数据”实现TCP心跳包所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部