private void DoEventClient(byte[] data) { if (ReceiveClientData != null) { Task.Factory.StartNew(() => { AsyncTcpUserToken token = new AsyncTcpUserToken(); token.Remote = asyncUser.Remote; token.IPAddress = asyncUser.IPAddress; ReceiveClientData(token, data); }); } else { AsyncTcpUserToken token = null; if (queue.Count > 1000) { queue.TryTake(out token); } token = new AsyncTcpUserToken(); token.Remote = asyncUser.Remote; token.IPAddress = asyncUser.IPAddress; token.Data = data; queue.TryAdd(token); } }
/// <summary> /// 初始化 /// </summary> private void Init() { if (!IsFixCacheSize) { m_bufferManager.MaxBufferCount = totalBufSize * 1024 * 1024 * 1024;//可以使用最多缓存 } m_clients = new List <AsyncTcpUserToken>(); SocketAsyncEventArgs readWriteEventArg; for (int i = 0; i < m_maxConnectNum; i++) { readWriteEventArg = new SocketAsyncEventArgs(); readWriteEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed); AsyncTcpUserToken userToken = new AsyncTcpUserToken(); userToken.Server = this; readWriteEventArg.UserToken = userToken; // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object if (IsFixCacheSize) { m_bufferManager.SetBuffer(readWriteEventArg); } else { m_bufferManager.GetBuffer(readWriteEventArg); } // add SocketAsyncEventArg to the pool m_pool.Push(readWriteEventArg); } }
/// <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> /// 关闭客户端,此时任然在接收数据 /// 所以CloseClientSocket会被调用 /// </summary> /// <param name="token"></param> public void CloseClient(AsyncTcpUserToken token) { try { token.Socket.Shutdown(SocketShutdown.Both); } catch (Exception) { } }
/// <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="readEventArgs"></param> private void ProcessReceive(SocketAsyncEventArgs readEventArgs) { try { // check if the remote host closed the connection AsyncTcpUserToken token = (AsyncTcpUserToken)readEventArgs.UserToken; if (readEventArgs.BytesTransferred > 0 && readEventArgs.SocketError == SocketError.Success) { //读取数据;这里也可以考虑建立缓存池获取 byte[] data = new byte[readEventArgs.BytesTransferred]; Array.Copy(readEventArgs.Buffer, readEventArgs.Offset, data, 0, readEventArgs.BytesTransferred); //lock (token.Buffer) //{ // token.Buffer.AddRange(data); //} //考虑道客户端数据大小,所以接收到一个缓存大小数据 //交给后端处理;socket作为基础操作,只管接收 if (EnableHeart && data.Length == HeartClient.Length) { if (Enumerable.SequenceEqual(data, HeartClient)) { //收到心跳 Console.WriteLine("收到客户端心跳"); token.Socket.Send(HeartServer); token.DataTime = DateTime.Now; if (!token.Socket.ReceiveAsync(readEventArgs)) { this.ProcessReceive(readEventArgs); } return; } } if (ReceiveClientData != null) { ReceiveClientData(token, data); } //继续接收下一次客户端发送的数据 //也可能是客户端发送过大,一个buffer接收不了 if (!token.Socket.ReceiveAsync(readEventArgs)) { this.ProcessReceive(readEventArgs); } } else { CloseClientSocket(readEventArgs); } } catch (Exception xe) { //RuncomLib.Log.LogUtils.Info(xe.Message + "\r\n" + xe.StackTrace); } }
/// <summary> /// 处理连接 /// </summary> /// <param name="acceptEventArg"></param> private void ProcessAccept(SocketAsyncEventArgs acceptEventArg) { try { Interlocked.Increment(ref m_clientCount); SocketAsyncEventArgs readEventArgs = m_pool.Pop(); AsyncTcpUserToken userToken = (AsyncTcpUserToken)readEventArgs.UserToken; if (userToken == null) { //说明是新的,已经使用的读写还没有返回 userToken = new AsyncTcpUserToken(); readEventArgs.UserToken = userToken; readEventArgs.Completed += IO_Completed; userToken.Server = this; if (IsFixCacheSize) //分配缓存 { m_bufferManager.SetBuffer(readEventArgs); } else { m_bufferManager.GetBuffer(readEventArgs); } } userToken.Socket = acceptEventArg.AcceptSocket; userToken.ConnectTime = DateTime.Now; userToken.Remote = acceptEventArg.AcceptSocket.RemoteEndPoint; userToken.IPAddress = ((IPEndPoint)(acceptEventArg.AcceptSocket.RemoteEndPoint)).Address; lock (m_clients) { m_clients.Add(userToken); } if (ClientNumberChange != null) { //防止同步,不返回,无法绑定数据接收 Task.Factory.StartNew(() => { ClientNumberChange(1, userToken); }); } //获取到连接后立即准备接收数据;绑定接收事件 if (!acceptEventArg.AcceptSocket.ReceiveAsync(readEventArgs)) { ProcessReceive(readEventArgs); } } catch (Exception ex) { //RuncomLib.Log.LogUtils.Info(me.Message + "\r\n" + me.StackTrace); } if (acceptEventArg.SocketError == SocketError.OperationAborted) { return; } StartAccept(acceptEventArg); }
private void Server_ReceiveClientData(AsyncTcpUserToken token, byte[] buff) { if (token.TokenID == 0) { token.TokenID = Interlocked.Increment(ref clientID); token.DataTime = DateTime.Now; dic_Client[token.TokenID] = token; } if (ReceiveClientData != null) { ReceiveClientData(token, buff); } }
/// <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 = 0) { if (len == 0) { SendMessage(token, message); } else { byte[] tmp = new byte[len]; Array.Copy(message, offset, tmp, 0, len); SendMessage(token, tmp); } }
private void Client_ReceiveClientData(AsyncTcpUserToken token, byte[] buff) { asyncUser = token; //收集数据 lock (lst) { if (isPack) { lst.AddRange(buff); if (currentSize < 0 && lst.Count > 4) { currentSize = BitConverter.ToInt32(lst.GetRange(0, 4).ToArray(), 0); head = 4; } if (lst.Count > currentSize) { //说明数据收集完成 byte[] tmp = new byte[currentSize]; lst.CopyTo(head, tmp, 0, tmp.Length); //去除头 DoEventClient(tmp); lst.RemoveRange(0, currentSize + head); //包括头 if (lst.Count > 4) { currentSize = BitConverter.ToInt32(lst.GetRange(0, 4).ToArray(), 0); head = 4; } else { currentSize = -1; } } else if (lst.Count > maxSize) { //byte[] tmp= lst.ToArray(); //DoEventClient(tmp); //lst.Clear(); //currentSize -= lst.Count; byte[] tmp = new byte[maxSize]; lst.CopyTo(head, tmp, 0, tmp.Length);//去除头 DoEventClient(tmp); currentSize = currentSize - (maxSize + head); head = 0; } } else { DoEventClient(buff); } } }
/// <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="buff"></param> private void DoReceiveEvent(byte[] buff) { if (ReceiveClientData != null) { Task.Factory.StartNew(() => { AsyncTcpUserToken token = new AsyncTcpUserToken(); if (string.IsNullOrEmpty(LocalHost)) { IPEndPoint point = socket.LocalEndPoint as IPEndPoint; LocalHost = point.Address.ToString(); } token.IPAddress = IPAddress.Parse(LocalHost); token.Remote = endPoint; token.Socket = socket; token.Client = this; ReceiveClientData(token, buff); }); } }
private void Server_ClientNumberChange(int num, AsyncTcpUserToken token) { if (num > 0) { token.DataTime = DateTime.Now; if (token.TokenID == 0) { token.TokenID = Interlocked.Increment(ref clientID); dic_Client[token.TokenID] = token; } } else { AsyncTcpUserToken tmp = null; dic_Client.TryRemove(token.TokenID, out tmp); } if (ClientNumberChange != null) { ClientNumberChange(num, token); } }
/// <summary> /// 发送心跳 /// </summary> /// <param name="token"></param> public void SendHeart(AsyncTcpUserToken token) { bool isSucess = false; if (token.Socket.Connected) { try { token.Socket.Send(HeartServer); isSucess = true; } catch (Exception ex) { Console.WriteLine(ex.Message); } } if (!isSucess) { CloseClient(token); } }
/// <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="token"></param> public void CloseClient(AsyncTcpUserToken token) { server.CloseClient(token); }
/// <summary> /// 对数据按照服务端缓存分包 /// 然后发送 /// </summary> /// <param name="token"></param> /// <param name="message"></param> /// <returns></returns> public void SendMessage(AsyncTcpUserToken token, byte[] message) { if (token == null || token.Socket == null || !token.Socket.Connected) { return; } try { //token.Socket.Send(buff); //这句也可以发送, 可根据自己的需要来选择 //新建异步发送对象, 发送消息 int index = 0; int len = 0; do { SocketAsyncEventArgs sendArg = m_pool.Pop(); if (null == sendArg.UserToken) { //说明是新建 sendArg.Completed += this.IO_Completed; //m_bufferManager.SetBuffer(sendArg); if (IsFixCacheSize) //分配缓存 { m_bufferManager.SetBuffer(sendArg); } else { m_bufferManager.GetBuffer(sendArg); } } sendArg.UserToken = token; byte[] buf = sendArg.Buffer; int curLen = message.Length - index; if (curLen < sendArg.Count) { //重新开辟缓存,原缓存不合适 if (sendArg.Buffer != null) { if (IsFixCacheSize) //分配缓存 { m_bufferManager.FreeBuffer(sendArg); } else { m_bufferManager.FreePoolBuffer(sendArg); } } sendArg.SetBuffer(new byte[curLen], 0, curLen); Array.Copy(message, index, sendArg.Buffer, sendArg.Offset, curLen); index += curLen; if (token.Socket.SendAsync(sendArg)) { ProcessSend(sendArg); } } else { len = sendArg.Count; Array.Copy(message, index, buf, sendArg.Offset, len); index += len; if (token.Socket.SendAsync(sendArg)) { ProcessSend(sendArg); } } } while (index >= message.Length); } catch (Exception e) { Console.WriteLine(e.Message); } }