using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; namespace Sog { /// /// session的轮询管理 /// public class AcceptedSessionUpdateAsyncMode { private Dictionary m_sessionDict = new Dictionary(); private SessionListener m_listener; //临时存放所有出错的socket private List m_needCloseList = new List(); private object m_needCloseListLocker = new object(); private long m_lastCheckSendKeepAliveTime; private List m_asyncAddedSessions = new List(); private object m_asyncAddedSessionsLocker = new object(); public AcceptedSessionUpdateAsyncMode(SessionListener listener) { m_listener = listener; } public int GetSessionCount() { return m_sessionDict.Count + m_asyncAddedSessions.Count; } public void AddAsync(NetSession session) { if (session.WorkSocket == null) { return; } lock(m_asyncAddedSessionsLocker) { m_asyncAddedSessions.Add(session); } } public void Close() { m_sessionDict.Clear(); m_asyncAddedSessions.Clear(); } public void Update(long nowMs) { if (nowMs - m_lastCheckSendKeepAliveTime >= 10000) { m_lastCheckSendKeepAliveTime = nowMs; //keep alive foreach (var pair in m_sessionDict) { NetSession session = pair.Value; if (session.IsSocketClosed == false) { session.StartSendAsync(); } } } foreach (var pair in m_sessionDict) { NetSession session = pair.Value; Socket socket = pair.Key; if (session.IsSocketClosed) { AddSocketToNeedClose(socket); } } CloseNeedCloseSocket(); //异步添加的session在这里放到dict里去 if(m_asyncAddedSessions.Count > 0) { lock(m_asyncAddedSessionsLocker) { foreach(var session in m_asyncAddedSessions) { if (session.WorkSocket != null) { m_sessionDict.Add(session.WorkSocket, session); } } m_asyncAddedSessions.Clear(); } } } public void ForceAsyncCloseSession(NetSession session) { AddSocketToNeedClose(session.WorkSocket); } private void AddSocketToNeedClose(Socket socket) { if(socket == null) { return; } lock(m_needCloseListLocker) { // if (m_needCloseList.Contains(socket)) // { // return; // } m_needCloseList.Add(socket); } } private void CloseNeedCloseSocket() { if(m_needCloseList.Count == 0) { return; } List closeSocket; lock (m_needCloseListLocker) { closeSocket = m_needCloseList.ToList(); m_needCloseList.Clear(); } foreach (Socket socket in closeSocket) { if (m_sessionDict.TryGetValue(socket, out NetSession session)) { m_sessionDict.Remove(socket); SessionEventArgs e = new SessionEventArgs(); e.Session = session; m_listener.OnDisconnected(e); TraceLog.Trace("AcceptedSessionUpdateAsyncMode.CloseNeedCloseSocket session {0}", session.SessionID); session.Close(); } } } } }