//关闭客户端 void CloseClientSocketEx(SocketAsyncEventArgs e, SocketColseType colseType) { AsyncUserToken token = e.UserToken as AsyncUserToken; if (token != null) { if (token.Socket != null && token.Socket.Connected) { token.Socket.Shutdown(SocketShutdown.Both); token.Socket.Close(); } } onSocketClose(token.ConnId, colseType); semaphore.Release(); lock (m_pool) { if (m_pool.Count < m_maxConnectNum) { e.UserToken = new AsyncUserToken(); m_pool.Push(e); } } }
/// <summary> /// 发送数据方法 /// </summary> /// <param name="socket">客户端socket</param> /// <param name="message">要发送的数据</param> bool WebSocketSend(AsyncUserToken token, string message) { var socket = token.Socket; byte[] bytes = Comm.StringToBytes(message); bool send = true; int SendMax = bufferSize; //每次分片最大1kb数据 int count = 0; //发送的次数 int sendedlen = 0; //已经发送的字节长度 while (send) { byte[] contentBytes = null;//待发送的消息内容 var sendArr = bytes.Skip(count * SendMax).Take(SendMax).ToArray(); sendedlen += sendArr.Length; if (sendArr.Length > 0) { send = bytes.Length > sendedlen;//是否继续发送 if (sendArr.Length < 126) { contentBytes = new byte[sendArr.Length + 2]; contentBytes[0] = (byte)(count == 0 ? 0x81 : (!send ? 0x80 : 0)); contentBytes[1] = (byte)sendArr.Length;//1个字节存储真实长度 Array.Copy(sendArr, 0, contentBytes, 2, sendArr.Length); send = false; } else if (sendArr.Length <= 65535) { contentBytes = new byte[sendArr.Length + 4]; if (!send && count == 0) { contentBytes[0] = 0x81;//非分片发送 } else { contentBytes[0] = (byte)(count == 0 ? 0x01 : (!send ? 0x80 : 0));//处于连续的分片发送 } contentBytes[1] = 126; byte[] slen = BitConverter.GetBytes((short)sendArr.Length);//2个字节存储真实长度 contentBytes[2] = slen[1]; contentBytes[3] = slen[0]; Array.Copy(sendArr, 0, contentBytes, 4, sendArr.Length); } else if (sendArr.LongLength < long.MaxValue) { contentBytes = new byte[sendArr.Length + 10]; contentBytes[0] = (byte)(count == 0 ? 0x01 : (!send ? 0x80 : 0)); //处于连续的分片发送 contentBytes[1] = 127; byte[] llen = BitConverter.GetBytes((long)sendArr.Length); //8个字节存储真实长度 for (int i = 7; i >= 0; i--) { contentBytes[9 - i] = llen[i]; } Array.Copy(sendArr, 0, contentBytes, 10, sendArr.Length); } } SocketAsyncEventArgs sendArg = new SocketAsyncEventArgs(); sendArg.SetBuffer(contentBytes, 0, contentBytes.Length); socket.SendAsync(sendArg); count++; } return(true); }
/// <summary> /// 接受数据 /// </summary> /// <param name="e"></param> private void ProcessReceive(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; if (e.SocketError == SocketError.Success) { if (e.BytesTransferred > 0) { byte[] data = new byte[e.BytesTransferred]; Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred);//把当前所接收到数据放到data数组里面 if (token.SocketConnType == SocketConnType.None) { token.SocketConnType = PacketComm.GetPacketType(data, out string packetStr); if (token.SocketConnType == SocketConnType.WebSocket) //websocket连接 { var HandPacket = Comm.BytesToString(PacketComm.AnswerWebSocketHandShake(packetStr)); //应答握手包 Send(token, HandPacket); } } else if (token.SocketConnType == SocketConnType.WebSocket)//WebSocket数据包 { var Pac_Type = data[0] & 0xF; if (Pac_Type == 8)//WebSocket关闭 { CloseClientSocketEx(e, SocketColseType.ClientClose); } else { #region WebSocket数据包 https://www.cnblogs.com/smark/archive/2012/11/26/2789812.html lock (token.Buffer) token.Buffer.AddRange(data); if (token.Socket.Available == 0)//接受完毕 { var buffer = token.Buffer.ToArray(); var len = buffer.Length; bool mask = false; int lodlen = 0; if (len > 2) { var Pac_Fin = (buffer[0] >> 7) > 0;//是否最后一个数据包 if (Pac_Fin) { mask = (buffer[1] >> 7) > 0; lodlen = buffer[1] & 0x7F; byte[] loddata; byte[] masks = new byte[4]; if (lodlen == 126) { Array.Copy(buffer, 4, masks, 0, 4); lodlen = (UInt16)(buffer[2] << 8 | buffer[3]); loddata = new byte[lodlen]; Array.Copy(buffer, 8, loddata, 0, lodlen); } else if (lodlen == 127) { Array.Copy(buffer, 10, masks, 0, 4); byte[] uInt64Bytes = new byte[8]; for (int i = 0; i < 8; i++) { uInt64Bytes[i] = buffer[9 - i]; } lodlen = (int)BitConverter.ToUInt64(uInt64Bytes, 0); loddata = new byte[lodlen]; for (int i = 0; i < lodlen; i++) { loddata[i] = buffer[i + 14]; } } else { Array.Copy(buffer, 2, masks, 0, 4); loddata = new byte[lodlen]; Array.Copy(buffer, 6, loddata, 0, lodlen); } for (var i = 0; i < lodlen; i++) { loddata[i] = (byte)(loddata[i] ^ masks[i % 4]); } var Message = Comm.BytesToString(loddata); onReceiveData(token.ConnId, Message, e); } } lock (token.Buffer) token.Buffer.Clear(); } #endregion } } if (token.SocketConnType == SocketConnType.Socket)//原生Socket数据包 { #region 原生Socket数据包 lock (token.Buffer) token.Buffer.AddRange(data); do { //**************************包头前8个字节为2个整数,第一个无意义默认为1,第二个为包长****************************************** byte[] lenBytes = token.Buffer.GetRange(4, 4).ToArray(); int packageLen = Comm.BytesToInt32(lenBytes, 0); if (packageLen > token.Buffer.Count - 8) { break; } byte[] rev = token.Buffer.GetRange(8, packageLen).ToArray();//获取从第8个字节起的净内容(加密过的内容) var Message = Comm.AESDecrypt(Comm.BytesToString(rev), AESKey); lock (token.Buffer) token.Buffer.RemoveRange(0, packageLen + 8); //从数据池中移除这组数据 onReceiveData(token.ConnId, Message, e); } while (token.Buffer.Count > 8); //(前4个字节是gameserverid(int),随后四个字节是内容总长度(int)) #endregion } if (token.Socket != null && token.Socket.Connected == true && !token.Socket.ReceiveAsync(e)) { ProcessReceive(e);//继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明 } } else { CloseClientSocketEx(e, SocketColseType.ClientClose); } } else { CloseClientSocketEx(e, SocketColseType.ClientClose); } }