/// <summary> /// 解析8字节命令部分 /// </summary> /// <param name="e"></param> private void ProcessReceivePackagePrefix(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; LogHelper.Log.InfoFormat("客户端{0}:In ProcessReceivePackagePrefix", token.Socket.RemoteEndPoint.ToString()); if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { for (int i = e.Offset; i < e.BytesTransferred; i++) { token.resultBytes.Add(e.Buffer[i]); } if (token.resultBytes.Count < token.Length) { e.SetBuffer(e.Offset, token.Length - token.resultBytes.Count); token.CommandType = CommandType.PackagePrefix; bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } } else { BasicPackage package = SocketHelper.BytesToStruct <BasicPackage>(token.resultBytes.ToArray()); package.PID = SocketHelper.NetworkToHost(package.PID); package.CID = SocketHelper.NetworkToHost(package.CID); package.VER = SocketHelper.NetworkToHost(package.VER); token.resultBytes.Clear(); if (package.VER == FuncCode.ALPVERSION) { token.BasicPackage = package; this.ParseCommand(e); } else { this.CloseClientSocket(e); LogHelper.Log.InfoFormat("协议版本错误,当前版为:{0},需求版本为:{1}", package.VER, FuncCode.ALPVERSION); } } } else { this.CloseClientSocket(e); } }
/// <summary> /// 关闭连接,释放资源 /// </summary> /// <param name="e"></param> private void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = e.UserToken as AsyncUserToken; LogHelper.Log.InfoFormat("客户端{0}:In CloseClientSocket", token.Socket.RemoteEndPoint.ToString()); try { token.Socket.Shutdown(SocketShutdown.Send); } catch (Exception) { } token.Socket.Close(); token = null; e.UserToken = null; e.UserToken = new AsyncUserToken(); Interlocked.Decrement(ref this.m_numConnectedSockets); this.m_maxNumberAcceptedClients.Release(); this.m_readWritePool.Push(e); this.m_UsedObjects.Remove(e); }
/// <summary> /// /// </summary> /// <param name="e"></param> private void ProcessSend(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; LogHelper.Log.InfoFormat("客户端{0}:In ProcessSend", token.Socket.RemoteEndPoint.ToString()); if (e.SocketError == SocketError.Success) { bool willRaiseEvent = false; switch (token.CommandType) { case CommandType.Ensure: case CommandType.Login: case CommandType.EnumData: case CommandType.PushDataRequest: case CommandType.NullCommand: case CommandType.PushDataReply: token.CommandType = CommandType.PackagePrefix; e.SetBuffer(e.Offset, PackgeSize.BasicPackageSize); willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } break; case CommandType.Close: this.CloseClientSocket(e); break; default: break; } } else { this.CloseClientSocket(e); } }
/// <summary> /// 获取数据项的值部分 /// </summary> /// <param name="e"></param> private void ProcessReceivePushDataRecordBody(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; LogHelper.Log.InfoFormat( "客户端{0}:In ProcessReceivePushDataRecordBody", token.Socket.RemoteEndPoint.ToString()); if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { for (int i = e.Offset; i < e.BytesTransferred; i++) { token.resultBytes.Add(e.Buffer[i]); } if (token.resultBytes.Count < token.Length) { e.SetBuffer(e.Offset, token.Length - token.resultBytes.Count); token.CommandType = CommandType.PushDataRecordBody; bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } } else { token.Value = token.resultBytes.ToArray(); var item = new DataItem() { Id = token.DID, Type = token.DT, Value = token.Value }; LogHelper.Log.InfoFormat( "客户端{0}:接收到数据项编号 - {1},类型 - {2},值 - {3}", token.Socket.RemoteEndPoint.ToString(), token.DID, token.DT, SocketHelper.GetValueByType(item)); token.DataItems.Add(item); token.InsertedCount++; token.resultBytes.Clear(); if (token.InsertedCount < token.CollectDataCount) { token.CommandType = CommandType.PushDataRecordHead; e.SetBuffer(e.Offset, PackgeSize.BasicPackageSize); bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } } else { if (token.MongoHelper.InsertValueToMongo(token.Machine, token.DataItems) == 1) { LogHelper.Log.InfoFormat( "客户端{0}:所有推送数据已接收,等待下一次推送", token.Socket.RemoteEndPoint.ToString()); token.DataItems.Clear(); token.InsertedCount = 0; LogHelper.Log.InfoFormat("客户端{0}:发送推送数据回复", token.Socket.RemoteEndPoint.ToString()); token.CommandType = CommandType.PushDataReply; BasicPackage package8 = new BasicPackage(); package8.PID = SocketHelper.HostToNetwork((ushort)0x0000); package8.CID = SocketHelper.HostToNetwork(FuncCode.PushDataReply); package8.ST = 0; package8.UID = Convert.ToByte(token.UserName); package8.VER = SocketHelper.HostToNetwork((ushort)0x1000); var result = SocketHelper.StructToBytes(package8); e.SetBuffer(e.Offset, 8); Buffer.BlockCopy(result, e.Offset, e.Buffer, 0, 8); LogHelper.Log.InfoFormat( "向客户端{0}:发送登录请求报文,长度为{1}", token.Socket.RemoteEndPoint.ToString(), result.Length); bool willRaiseEvent = token.Socket.SendAsync(e); if (!willRaiseEvent) { this.ProcessSend(e); } } else { this.CloseClientSocket(e); } } } } else { this.CloseClientSocket(e); } }
/// <summary> /// 解析具体枚举数据项 /// </summary> /// <param name="e"></param> private void ProcessReceiveEnumDataRecord(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; LogHelper.Log.InfoFormat("客户端{0}:In ProcessReceiveEnumDataRecord", token.Socket.RemoteEndPoint.ToString()); if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { for (int i = e.Offset; i < e.BytesTransferred; i++) { token.resultBytes.Add(e.Buffer[i]); } if (token.resultBytes.Count < token.Length) { e.SetBuffer(e.Offset, token.Length - token.resultBytes.Count); token.CommandType = CommandType.EnumDataRecord; bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } } else { EnumDataRecordPackage package = SocketHelper.BytesToStruct <EnumDataRecordPackage>(token.resultBytes.ToArray()); package.DID = SocketHelper.NetworkToHost(package.DID); token.Machine.Map.MapArray.Add( new MapArray() { Id = package.DID.ToString(), Value = package.NAME }); LogHelper.Log.InfoFormat( "客户端{0}:接收枚举数据项编号{1},名称{2}", token.Socket.RemoteEndPoint.ToString(), package.DID.ToString(), package.NAME); token.InsertedCount++; token.resultBytes.Clear(); if (token.InsertedCount < token.MappedFieldCount) { e.SetBuffer(e.Offset, PackgeSize.EnumDataPackageSize); token.CommandType = CommandType.EnumDataRecord; bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } } else { token.InsertedCount = 0; if (token.MongoHelper.InsertMappedFiled(token.Machine) == 1) { RequestPushPackage package6 = new RequestPushPackage(); package6.PID = SocketHelper.HostToNetwork((ushort)0x0000); package6.CID = SocketHelper.HostToNetwork(FuncCode.PushDataRequest); package6.UID = (byte)token.UserName; package6.ST = 0; package6.VER = SocketHelper.HostToNetwork((ushort)0x1000); package6.RV = new byte[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; token.CommandType = CommandType.PushDataRequest; var result = SocketHelper.StructToBytes(package6); e.SetBuffer(e.Offset, PackgeSize.RequestPushPackageSize); Buffer.BlockCopy(result, e.Offset, e.Buffer, 0, PackgeSize.RequestPushPackageSize); LogHelper.Log.InfoFormat( "向客户端{0}:发送推送数据请求报文,长度为{1}", token.Socket.RemoteEndPoint.ToString(), result.Length); bool willRaiseEvent = token.Socket.SendAsync(e); if (!willRaiseEvent) { this.ProcessSend(e); } } else { this.CloseClientSocket(e); } } } } else { this.CloseClientSocket(e); } }
/// <summary> /// 设备自举 /// </summary> /// <param name="e"></param> private void ProcessReceiveBootstrap(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; LogHelper.Log.InfoFormat("客户端{0}:In ProcessReceivePackagePrefix", token.Socket.RemoteEndPoint.ToString()); if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { for (int i = e.Offset; i < e.BytesTransferred; i++) { token.resultBytes.Add(e.Buffer[i]); } if (token.resultBytes.Count < token.Length) { e.SetBuffer(e.Offset, token.Length - token.resultBytes.Count); token.CommandType = CommandType.Bootstrap; bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } } else { MacBootstrapPackage package = SocketHelper.BytesToStruct <MacBootstrapPackage>(token.resultBytes.ToArray()); token.Machine.MachineCode = SocketHelper.BinToHexString(package.DID).TrimEnd().ToUpper(); LogHelper.Log.InfoFormat( "客户端{0}:接收到自举设备编号{1}", token.Socket.RemoteEndPoint.ToString(), token.Machine.MachineCode); token.resultBytes.Clear(); if (token.MongoHelper.GetMacLoginInfo(token) == 1) { LoginPackage package4 = new LoginPackage(); package4.PID = SocketHelper.HostToNetwork((ushort)0x0000); package4.CID = SocketHelper.HostToNetwork(FuncCode.Login); package4.ST = 0; package4.UID = Convert.ToByte(token.UserName); package4.VER = SocketHelper.HostToNetwork((ushort)0x1000); package4.Password = token.Password.PadRight(8, '\0'); token.CommandType = CommandType.Login; var result = SocketHelper.StructToBytes(package4); e.SetBuffer(e.Offset, 16); Buffer.BlockCopy(result, e.Offset, e.Buffer, 0, 16); LogHelper.Log.InfoFormat( "向客户端{0}:发送登录请求报文,长度为{1}", token.Socket.RemoteEndPoint.ToString(), result.Length); bool willRaiseEvent = token.Socket.SendAsync(e); if (!willRaiseEvent) { this.ProcessSend(e); } } else { this.CloseClientSocket(e); LogHelper.Log.InfoFormat("没有该设备的登录信息或设备已停用"); } } } else { this.CloseClientSocket(e); } }
/// <summary> /// ProcessReceive /// </summary> /// <param name="e"></param> private void ProcessReceive(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; LogHelper.Log.InfoFormat("客户端{0}:In ProcessReceive", token.Socket.RemoteEndPoint.ToString()); if (e.SocketError == SocketError.Success) { switch (token.CommandType) { case CommandType.PackagePrefix: token.Length = 8; this.ProcessReceivePackagePrefix(e); break; case CommandType.Bootstrap: token.Length = 32; this.ProcessReceiveBootstrap(e); break; case CommandType.Login: token.Length = 8; this.ProcessReceiveLogin(e); break; case CommandType.EnumDataCount: token.Length = 8; this.ProcessReceiveEnumDataCount(e); break; case CommandType.EnumDataRecord: token.Length = 104; this.ProcessReceiveEnumDataRecord(e); break; case CommandType.PushDataRequest: token.Length = 8; this.ProcessReceivePushDataRequest(e); break; case CommandType.PushDataCount: token.Length = 8; this.ProcessReceivePushDataCount(e); break; case CommandType.PushDataRecordHead: token.Length = 8; this.ProcessReceivePushDataRecordHead(e); break; case CommandType.PushDataRecordBody: this.ProcessReceivePushDataRecordBody(e); break; case CommandType.Close: this.CloseClientSocket(e); break; case CommandType.NullCommand: token.CommandType = CommandType.NullCommandReply; this.ProcessSend(e); break; default: break; } } }
/// <summary> /// 解析命令 /// </summary> /// <param name="token"></param> private void ParseCommand(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; LogHelper.Log.InfoFormat("客户端{0}:In ParseCommand", token.Socket.RemoteEndPoint.ToString()); if (e.SocketError == SocketError.Success) { bool willRaiseEvent = false; switch (token.BasicPackage.CID) { case FuncCode.Bootstrap: e.SetBuffer(e.Offset, PackgeSize.MacBootstrapPackageSize); token.CommandType = CommandType.Bootstrap; willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } break; case FuncCode.Login: e.SetBuffer(e.Offset, PackgeSize.LoginPackageSize - PackgeSize.BasicPackageSize); token.CommandType = CommandType.Login; willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } break; case FuncCode.EnumData: e.SetBuffer(e.Offset, PackgeSize.LoginPackageSize - PackgeSize.BasicPackageSize); token.CommandType = CommandType.EnumDataCount; willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } break; case FuncCode.PushDataRequest: e.SetBuffer(e.Offset, PackgeSize.LoginPackageSize - PackgeSize.BasicPackageSize); token.CommandType = CommandType.PushDataRequest; willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } break; case FuncCode.PushData: e.SetBuffer(e.Offset, PackgeSize.LoginPackageSize - PackgeSize.BasicPackageSize); token.CommandType = CommandType.PushDataCount; willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { this.ProcessReceive(e); } break; case FuncCode.NullCommand: BasicPackage package7 = new BasicPackage(); package7.PID = SocketHelper.HostToNetwork((ushort)0x0000); package7.CID = SocketHelper.HostToNetwork(FuncCode.NullCommandReply); package7.ST = 0; package7.UID = Convert.ToByte(token.UserName); package7.VER = SocketHelper.HostToNetwork((ushort)0x1000); var result = SocketHelper.StructToBytes(package7); token.CommandType = CommandType.NullCommand; e.SetBuffer(e.Offset, 8); Buffer.BlockCopy(result, e.Offset, e.Buffer, 0, 8); LogHelper.Log.InfoFormat( "向客户端{0}发送心跳包回复报文,长度为{1}", token.Socket.RemoteEndPoint.ToString(), result.Length); willRaiseEvent = token.Socket.SendAsync(e); if (!willRaiseEvent) { this.ProcessSend(e); } break; case FuncCode.Close: this.CloseClientSocket(e); break; default: break; } } else { this.CloseClientSocket(e); } }
/// <summary> /// 守护线程检测会话超时 /// </summary> private void DaemonThreadStart() { while (this.m_thread.IsAlive) { LogHelper.Log.InfoFormat("当前连接数量{0}", this.m_UsedObjects.Count); for (int i = 0; i < this.m_UsedObjects.Count; i++) { if (!this.m_thread.IsAlive) { break; } try { lock (this.m_UsedObjects[i].UserToken) { AsyncUserToken token = this.m_UsedObjects[i].UserToken as AsyncUserToken; if (token != null) { var currentDateTime = DateTime.Now; if ((currentDateTime - token.ActiveDateTime).TotalSeconds > SocketTimeOutMS) { // 超时Socket断开 LogHelper.Log.InfoFormat( "连接超时,当前连接设备为{0},当前时间为{1},最后通讯时间为{2}", token.TenantId, currentDateTime, token.ActiveDateTime); if (token.IsLogined) { // 设置此时设备是离线状态 StateArray item = new StateArray() { Code = "4", CreationTime = DateTime.Now.ToString("yyyyMMddHHmmss") }; token.MongoHelper.InsertStateData( token.Machine.TenantId, token.Machine.MachineCode, item); // 结束报警时间 AlarmArray item2 = new AlarmArray() { Code = "0", CreationTime = DateTime.Now.ToString("yyyyMMddHHmmss") }; token.MongoHelper.InsertAlarmData( token.Machine.TenantId, token.Machine.MachineCode, item2); } this.CloseClientSocket(this.m_UsedObjects[i]); } } } } catch (Exception e) { CGLogger.Error(e.Message.ToString()); } } for (int i = 0; i < 60; i++) { // 每分钟检测一次 if (!this.m_thread.IsAlive) { break; } Thread.Sleep(1000); } } }