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 } |
C# 实现的多线程异步Socket数据包接收器框架(3)
最新推荐文章于 2021-06-21 14:01:42 发布