private void OnClientState(ClientBase client, bool isConnected) { ClientState?.Invoke(this, client, isConnected); if (!isConnected) { RemoveClient(client); } }
/// <summary> /// 关闭socket客户端 /// </summary> /// <param name="e"></param> private void CloseClientSocket(SocketAsyncEventArgs e) { try { HCClient token = e.UserToken as HCClient; if (m_clientPool.Contains(e)) { //关闭与客户端连接的socket try { token.Socket.Shutdown(SocketShutdown.Both); } catch (Exception) { //客户端已经关闭 } ClientState?.Invoke(HCClientStateEnmu.Disconnected, token); //客户端断开连接 token.Socket.Close(); token.ClearCache(); //连接数递减 Interlocked.Decrement(ref m_numConnectedSockets); //释放SocketAsyncEventArgs,以便其他客户端可以重用它们 m_readPool.Push(e); m_clientPool.Remove(e); m_maxNumberAcceptedClients.Release(); Console.WriteLine("客户端从服务器断开连接,当前服务器客户端连接数:{0}", m_numConnectedSockets); } else { Console.WriteLine("客户端从服务器断开连接"); } } catch (Exception exp) { ServerState?.Invoke(HCServerStateEnmu.RunningException, exp.Message); } }
/// <summary> /// 客户端接收到消息 /// </summary> /// <param name="state"></param> /// <param name="msg"></param> private void HCServer_ClientDataState(HCDataStateEnmu state, HCMessage msg) { try { if (msg.ClientID == "") { //没有客户端ID,解析ID string[] info = msg.GetDataString().Split(new string[] { "/" }, StringSplitOptions.None); string ver = info[0]; //协议版本号 msg.ClientID = info[1]; //客户端ID msg.HCClient.ClientID = info[1]; //客户端ID ClientState?.Invoke(HCClientStateEnmu.Connected, msg.HCClient); //客户端连接成功(业务逻辑上成功) } else { ClientDataState?.Invoke(state, msg); } } catch (Exception e) { ServerState?.Invoke(HCServerStateEnmu.RunningException, e.Message); } }
/// <summary> /// 解析接收到的数据 /// </summary> /// <param name="data"></param> public void AnalysisData(byte[] data) { try { Console.WriteLine("准备解析数据:"); m_pingcount = 0; if (data.Length < 4) { Console.WriteLine("解析数据的长度小于4个,数据进入缓冲区"); if (datacache.Count + data.Length < 4) {//缓冲区与新添加的数据不够4个字节 Console.WriteLine("缓冲区已有数据与数据长度总长小于4,数据追加进入缓冲区,并准备接收下一次数据"); datacache.AddRange(data); return; } } if (datacache.Count == 0) { //缓冲区没有数,需要处理的数据是带包头的 Console.WriteLine("缓冲区无数据,本次数据包含包头数据"); byte[] datalength = new byte[4]; //获取包头 Array.Copy(data, 0, datalength, 0, datalength.Length); Console.WriteLine("输出包头" + datalength[0] + " " + datalength[1] + " " + datalength[2] + " " + datalength[3]); Array.Reverse(datalength); //倒转数据 uint packagelength = BitConverter.ToUInt32(datalength, 0); //读取到包的长度 Console.WriteLine("本次数据包长度为:" + packagelength + ";数据总长为:" + data.Length); if (packagelength == (data.Length - 4)) {//恰好一个数据包 Console.WriteLine("恰好一个完整的数据包"); if (packagelength == 1) {//ping包回馈 Console.WriteLine("ping包"); } else { Console.WriteLine("非ping包,准备传递数据"); byte[] msgdata = new byte[packagelength]; Array.Copy(data, 4, msgdata, 0, msgdata.Length); ClientDataState?.Invoke(HCDataStateEnmu.Received, new HCMessage(this, msgdata)); } } else if (packagelength < (data.Length - 4)) {//粘包情况 Console.WriteLine("粘包情况"); if (packagelength == 1) {//ping包回馈 Console.WriteLine("粘包中的ping包"); } else { Console.WriteLine("粘包中的非ping包,准备传递数据"); byte[] msgdata = new byte[packagelength]; Array.Copy(data, 4, msgdata, 0, msgdata.Length); ClientDataState?.Invoke(HCDataStateEnmu.Received, new HCMessage(this, msgdata)); } Console.WriteLine("继续处理剩下的粘包数据,长度:" + (data.Length - packagelength - 4)); byte[] datacontinue = new byte[data.Length - packagelength - 4]; Array.Copy(data, packagelength + 4, datacontinue, 0, datacontinue.Length); Console.WriteLine("继续处理的粘包数据头:" + data[packagelength] + " " + data[packagelength + 1] + " " + data[packagelength + 2] + " " + data[packagelength + 3]); AnalysisData(datacontinue); } else {//半包情况 Console.WriteLine("半包情况"); datacache.AddRange(data); if (packagelength <= datacache.Count - 4) {//缓冲区中数据可形成整包 Console.WriteLine("缓冲区中数据可形成整包,继续解析数据"); byte[] datacontinue = datacache.ToArray(); datacache.Clear(); AnalysisData(datacontinue); } } } else {//缓冲区有数据,接收到的数据是没有包头的 Console.WriteLine("缓冲区有数据,接收到的数据是没有包头的"); datacache.AddRange(data); byte[] datacontinue = datacache.ToArray(); datacache.Clear(); AnalysisData(datacontinue); } } catch (Exception exp) { ClientState?.Invoke(HCClientStateEnmu.RunningException, this); } }
private void OnClientState(Client client, bool isConnected) => ClientState?.Invoke(this, client, isConnected);