C# 实现的多线程异步Socket数据包接收器框架(3)

转载自 zhonghuafy

3.3 处理数据包

该线程循环查看数据包队列,完成数据包的解析与存储等工作。具体实现时,如果队列中没有数据包,可以考虑等待若干毫秒,提高CPU利用率。

Code
private void HandleDatagrams(object state)
{
while (!_stopReceiver)
{
this.HandleOneDatagram(); // 处理一个数据包

if (!_stopReceiver)
{
// 如果连接关闭,则重新建立,可容许几个连接错误出现
if (_sqlConnection.State == ConnectionState.Closed)
{
this.OnReceiverWork();

try
{
_sqlConnection.Open();
}
catch
{
this.OnReceiverException();
}
}
}
}
}

/// <summary>
/// 处理一个包数据,包括:验证、存储
/// </summary>
private void HandleOneDatagram()
{
TDatagram datagram
= null;

lock (_datagramQueue)
{
if (_datagramQueue.Count > 0)
{
datagram
= _datagramQueue.Dequeue(); // 取队列数据
Interlocked.Decrement(ref _datagramQueueCount);
}
}

if (datagram == null) return;

datagram.Clear();
datagram
= null; // 释放对象
}

3.4 检查与清理会话

本线程负责处理建立连接后的客户端会话TSession或Socket对象的关闭与资源清理工作,其它方法中出现异常等情况,尽可能标记相关TSession对象的属性NoReply=true,表示该会话已经无效、需要清理。

检查会话队列并清理资源分3步:第一步,Shutdown()客户端Socket,此时可能立即触发某些Socket的异步方法EndReceive();第二步,Close()客户端Socket,释放占用资源;第三步,从会话表中清除该会话对象。其中,第一步完成后,某个TSession也许不会立即到第二步,因为可能需要处理其异步结束方法。

需要指出, 由于涉及多线程处理,需要频繁加解锁操作,清理工作前先建立一个会话队列列副本sessionTable2,检查与清理该队副本列列的TSession对象。

Code
/// <summary>
/// 检查客户端状态(扫描方式,若长时间无数据,则断开)
/// </summary>
private void CheckClientState(object state)
{
while (!_stopReceiver)
{
DateTime thisTime
= DateTime.Now;

// 建立一个副本 ,然后对副本进行操作
Hashtable sessionTable2 = new Hashtable();
lock (_sessionTable)
{
foreach (TSession session in _sessionTable.Values)
{
if (session != null)
{
sessionTable2.Add(session.ID, session);
}
}
}

foreach (TSession session in sessionTable2.Values) // 对副本进行操作
{
Monitor.Enter(session);
try
{
if (session.State == TSessionState.NoReply) // 分三步清除一个 Session
{
session.State
= TSessionState.Closing;
if (session.ClientSocket != null)
{
try
{
// 第一步:shutdown
session.ClientSocket.Shutdown(SocketShutdown.Both);
}
catch { }
}
}
else if (session.State == TSessionState.Closing)
{
session.State
= TSessionState.Closed;
if (session.ClientSocket != null)
{
try
{
// 第二步: Close
session.ClientSocket.Close();
}
catch { }
}
}
else if (session.State == TSessionState.Closed)
{

lock (_sessionTable)
{
// 第三步:remove from table
_sessionTable.Remove(session.ID);
Interlocked.Decrement(
ref _clientCount);
}

this.OnClientRequest();
session.Clear();
// 清空缓冲区
}
else if (session.State == TSessionState.Normal) // 正常的会话
{

TimeSpan ts
= thisTime.Subtract(session.LastDataReceivedTime);
if (Math.Abs(ts.TotalSeconds) > _maxSocketDataTimeout) // 超时,则准备断开连接
{
session.DisconnectType
= TDisconnectType.Timeout;
session.State
= TSessionState.NoReply; // 标记为将关闭、准备断开
}
}
}
finally
{
Monitor.Exit(session);
}
}
// end foreach

sessionTable2.Clear();
}
// end while
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值