原文:C#高性能大容量SOCKET并发(六):超时Socket断开(守护线程)和心跳包

守护线程

在服务端版Socket编程需要处理长时间没有发送数据的Socket,需要在超时多长时间后断开连接,我们需要独立一个线程(DaemonThread)来轮询,在执行断开时,需要把Socket对象锁定,并调用CloseClientSocket来断开连接,具体处理代码如下:

namespace SocketAsyncSvr
{
class DaemonThread : Object
{
private Thread m_thread;
private AsyncSocketServer m_asyncSocketServer; public DaemonThread(AsyncSocketServer asyncSocketServer)
{
m_asyncSocketServer = asyncSocketServer;
m_thread = new Thread(DaemonThreadStart);
m_thread.Start();
} public void DaemonThreadStart()
{
while (m_thread.IsAlive)
{
AsyncSocketUserToken[] userTokenArray = null;
m_asyncSocketServer.AsyncSocketUserTokenList.CopyList(ref userTokenArray);
for (int i = 0; i < userTokenArray.Length; i++)
{
if (!m_thread.IsAlive)
break;
try
{
if ((DateTime.Now - userTokenArray[i].ActiveDateTime).Milliseconds > m_asyncSocketServer.SocketTimeOutMS) //超时Socket断开
{
lock (userTokenArray[i])
{
m_asyncSocketServer.CloseClientSocket(userTokenArray[i]);
}
}
}
catch (Exception E)
{
Program.Logger.ErrorFormat("Daemon thread check timeout socket error, message: {0}", E.Message);
Program.Logger.Error(E.StackTrace);
}
} for (int i = 0; i < 60 * 1000 / 10; i++) //每分钟检测一次
{
if (!m_thread.IsAlive)
break;
Thread.Sleep(10);
}
}
} public void Close()
{
m_thread.Abort();
m_thread.Join();
}
}
}

心跳包

有超时连接,相对应的需要设计心跳包,心跳包用来检测连接和维护连接状态,心跳包的原理是客户端发送一个包给服务器,服务器收到后发一个响应包给客户端,通过检测是否有返回来判断连接是否正常,心跳包实现放在BaseSocketProtocol.DoActive方法中。

        public bool DoActive()
{
m_outgoingDataAssembler.AddSuccess();
return DoSendResult();
}

具体由各个协议是否决定调用,如控制协议ControlSocketProtocol实现心跳协议如下:

        public override bool ProcessCommand(byte[] buffer, int offset, int count) //处理分完包的数据,子类从这个方法继承
{
ControlSocketCommand command = StrToCommand(m_incomingDataParser.Command);
m_outgoingDataAssembler.Clear();
m_outgoingDataAssembler.AddResponse();
m_outgoingDataAssembler.AddCommand(m_incomingDataParser.Command);
if (!CheckLogined(command)) //检测登录
{
m_outgoingDataAssembler.AddFailure(ProtocolCode.UserHasLogined, "");
return DoSendResult();
}
if (command == ControlSocketCommand.Login)
return DoLogin();
else if (command == ControlSocketCommand.Active)
return DoActive();
else if (command == ControlSocketCommand.GetClients)
return DoGetClients();
else
{
Program.Logger.Error("Unknow command: " + m_incomingDataParser.Command);
return false;
}
}

DEMO下载地址:http://download.csdn.net/detail/sqldebug_fan/7467745

免责声明:此代码只是为了演示C#完成端口编程,仅用于学习和研究,切勿用于商业用途。水平有限,C#也属于初学,错误在所难免,欢迎指正和指导。邮箱地址:fansheng_hx@163.com。

最新文章

  1. [AlwaysOn Availability Groups]使用Powershell监控AlwayOn健康
  2. codeforces 501C. Misha and Forest 解题报告
  3. [充电][库]Zlib文件压缩和解压
  4. C++ 表达式
  5. AJax跨域请求百度音乐接口数据展示页面
  6. UVA 558 Wormholes
  7. 警惕arm-linux-gcc编译器优化选项
  8. c语言命名规则 [转载]
  9. Linux tomcat部署War包,Linux在Tomcat部署JavaWeb项目,Linux部署War包
  10. fmt标签格式化数字和时间
  11. [区块链] 带你进入Bitcoin开发 - 环境搭建
  12. Redis宕机的问题
  13. 通过MTK迁移Mysql到EDB实战指南
  14. 简单修改文件名python脚本
  15. 03、 forms组件
  16. golang应用打包成docker镜像
  17. 解决 windows10和ubuntu16.04双系统下时间不对的问题
  18. 201621123006 《Java程序设计》第6周学习总结
  19. iframe相关知识
  20. Mimikatz.ps1本地执行

热门文章

  1. golang快速入门(练习)
  2. [转至云风的博客]开发笔记 (2) :redis 数据库结构设计
  3. 创建数据库以及其属性的sql语句
  4. .net程序客户端更新方案
  5. Linux初接触随笔02
  6. 【BZOJ 1034】[ZJOI2008]泡泡堂BNB
  7. Apacheserver自己定义404页面的两种方法以及.htaccess的重要命令总结
  8. 微信小程序实例:实现tabs选项卡效果
  9. jQuery插件实现的页面功能介绍引导页效果
  10. Codeforces 449 B. Jzzhu and Cities