private void IO_Completed(object sender, SocketAsyncEventArgs e) { switch (e.LastOperation) { case SocketAsyncOperation.Receive: ProcessReceive(e); break; case SocketAsyncOperation.Send: { lstSendArgs.Push(e); ProcessSend(e); if (e.UserToken.Equals("a") || e.UserToken.Equals("b")) { //不做 } else { CacheEntity entity = null; if (dic_entity.TryRemove(e.UserToken.ToString(), out entity)) { entity.Dispose(); } } } break; default: throw new ArgumentException("The last operation completed on the socket was not a receive or send"); } }
/// <summary> /// 关闭客户端通信 /// </summary> /// <param name="e"></param> private void CloseClientSocket(SocketAsyncEventArgs e) { AsyncTcpUserToken token = e.UserToken as AsyncTcpUserToken; lock (m_clients) { m_clients.Remove(token); } //如果有事件,则调用事件,发送客户端数量变化通知 if (ClientNumberChange != null) { ClientNumberChange(-1, token); } try { token.Socket.Shutdown(SocketShutdown.Send); } catch (Exception) { } token.Socket.Close(); Interlocked.Decrement(ref m_clientCount); if (token != null && !string.IsNullOrEmpty(token.UserInfo)) { CacheEntity entity = null; if (dic_Entity.TryRemove(token.UserInfo, out entity)) { //客户端发送使用的缓存要释放 entity.Dispose(); } e.UserToken = null; e.SetBuffer(null, 0, 0); e.Dispose();//新建的,必须释放,不是来自缓存 return; } //接收的一定是缓存的 e.UserToken = new AsyncTcpUserToken(); m_pool.Push(e); }
/// <summary> /// 使用缓存打包数据 /// </summary> /// <param name="data"></param> public void SendBufferPack(byte[] data) { int index = 0; CacheEntity entity = null; do { entity = DataPack.PackEntityTCP(data, ref index); client.SendEntity(entity); } while (entity != null && index < data.Length); }
/// <summary> /// 处理发送完成后的信息 /// </summary> /// <param name="e"></param> private void ProcessSend(SocketAsyncEventArgs e) { //TCP这里不好判断,缓存全部回收 if (e.SocketError == SocketError.Success) { // done echoing data back to the client //AsyncUserToken token = (AsyncUserToken)e.UserToken; // read the next block of data send from the client //bool willRaiseEvent = token.Socket.ReceiveAsync(e); //if (!willRaiseEvent) //{ // ProcessReceive(e); //} //发送完成回收 AsyncTcpUserToken token = e.UserToken as AsyncTcpUserToken; if (token != null && !string.IsNullOrEmpty(token.UserInfo)) { CacheEntity entity = null; if (dic_Entity.TryRemove(token.UserInfo, out entity)) { //客户端发送使用的缓存要释放 entity.Dispose(); } e.UserToken = null; e.SetBuffer(null, 0, 0); e.Dispose();//新建的,必须释放,不是来自缓存 return; } if (e.Count < m_bufferManager.BufferSize) { //直接释放内存,不是来自缓存 e.SetBuffer(null, 0, 0); e.UserToken = null; m_pool.Push(e); } else { //缓存回收,发送的需要回收,接收一定循环,发送不是 if (IsFixCacheSize) { m_bufferManager.FreeBuffer(e); } else { m_bufferManager.FreePoolBuffer(e); } m_pool.Push(e); } } else { CloseClientSocket(e); } }
/// <summary> /// 通过缓存发送数据 /// </summary> /// <param name="entity"></param> public void SendEntity(CacheEntity entity, string flage = "c") { string id = Interlocked.Increment(ref entityid).ToString(); dic_entity[id] = entity; if (entity.Fix == 0) { SendBuffer(entity.Buffer, entity.Offset, entity.Length, id); } else { Send(entity.Buffer, id); } }
/// <summary> /// /// </summary> /// <param name="token"></param> /// <param name="message"></param> /// <param name="offset"></param> /// <param name="len"></param> /// <param name="isCache"></param> public void SendPackage(AsyncTcpUserToken token, byte[] message, int offset, int len, int isCache = -1) { int index = 0; byte[] tmp = null; CacheEntity entity = null; switch (isCache) { case -1: server.SendPackage(token, message, offset, len); break; case 0: { do { tmp = DataPack.PackTCP(message, ref index); server.SendMessage(token, message); } while (tmp != null && index < message.Length); } break; case 1: { do { entity = DataPack.PackEntityTCP(message, ref index); server.SendData(token, entity); } while (entity != null && index < message.Length); } break; case 2: { do { entity = DataPack.PackEntityTCP(message, ref index); server.SendData(token, entity, "srv"); } while (entity != null && index < message.Length); } break; } }
/// <summary> /// 发送数据;从缓存中来的数据 /// </summary> /// <param name="token">客户端连接</param> /// <param name="entity">发送的缓存实体</param> /// <param name="flage">标记,默认null表示发送继续使用客户端缓存发送,否则由服务端分包使用服务端缓存发送</param> public void SendData(AsyncTcpUserToken token, CacheEntity entity, string flage = null) { if (string.IsNullOrEmpty(flage)) { //继续使用客户端缓存发送,不能分包使用服务端缓存 SocketAsyncEventArgs sendArg = new SocketAsyncEventArgs(); sendArg.Completed += this.IO_Completed; sendArg.SetBuffer(entity.Buffer, entity.Offset, entity.Length); token.UserInfo = Interlocked.Increment(ref entityid).ToString(); dic_Entity[token.UserInfo] = entity; sendArg.UserToken = token; if (token.Socket.SendAsync(sendArg)) { ProcessSend(sendArg); } } else { SendMessage(token, entity.Buffer); entity.Dispose(); } }
/// <summary> /// 数据分包,采用缓存 /// </summary> /// <param name="data"></param> /// <param name="index"></param> /// <returns></returns> public static CacheEntity PackEntityTCP(byte[] data, ref int index) { if (cacheTCP == null) { cacheTCP = new CacheManager(); cacheTCP.BufferSize = TcpPackSize; cacheTCP.MaxBufferCount = MaxUseBytes / TcpPackSize; } // CacheEntity entity = null; if (0 == index) { if (data.Length + 4 < TcpPackSize) { byte[] tmp = new byte[data.Length + 4]; Array.Copy(BitConverter.GetBytes(data.Length), 0, tmp, 0, 4); Array.Copy(data, 0, tmp, 4, data.Length); index += tmp.Length; entity = new CacheEntity(tmp, null); return(entity); } else { byte[] tmp = null; if (cacheTCP.GetBuffer(out tmp)) { entity = new CacheEntity(tmp, cacheTCP); } else { tmp = new byte[TcpPackSize]; entity = new CacheEntity(tmp, null); } Array.Copy(BitConverter.GetBytes(data.Length), 0, tmp, 0, 4); Array.Copy(data, 0, tmp, 4, TcpPackSize - 4); index += TcpPackSize - 4; return(entity); } } else if (index + TcpPackSize < data.Length) { byte[] tmp = null; if (cacheTCP.GetBuffer(out tmp)) { entity = new CacheEntity(tmp, cacheTCP); } else { tmp = new byte[TcpPackSize]; entity = new CacheEntity(tmp, null); } Array.Copy(data, tmp, TcpPackSize); index += TcpPackSize; return(entity); } else { if (data.Length - index <= 0) { return(null); } byte[] tmp = new byte[data.Length - index]; Array.Copy(data, tmp, tmp.Length); index += TcpPackSize; entity = new CacheEntity(tmp, null); return(entity); } }