public static void HandleReceivedPackages(ClientStateEventArgs e, Action <ClientStateEventArgs, IProtocolInfo> handleInnerProtocol) { string msg = string.Empty; if (e.LastPackages != null && e.LastPackages.Count > 0) { // 遍历接收到的多个封包数据 foreach (var package in e.LastPackages) { // 打开一个封包的内容,如果返回的结果为null,表示协议未知或者未能正常解析 IProtocolInfo protocol = ServerManager.DefaultPackageDealer.Open(package); if (protocol != null) { if (handleInnerProtocol != null) { handleInnerProtocol.BeginInvoke(e, protocol, null, null); } } else { logger.Debug("协议未知或者未能正常解析。"); } } } else { msg = e.LastReceivedMessage; logger.Debug("非协议消息" + msg); } }
public static void Send(IProtocolInfo info) { var messageThread = new Thread(() => { try { // 遍历所有客户端 foreach (var clientPair in StudentDevices) { var studentClient = clientPair.Value; //if (modifyInfoByClient != null) //{ // modifyInfoByClient(clientPair); //} if (studentClient != null) { IPackageInfo package = DefaultPackageDealer.Seal(info); TcpServer.SendAsync(studentClient, package.ToBytes()); } } } catch (Exception ex) { logger.Error(ex); } }); messageThread.Start(); }
public ConfigurationWriter(string hostFileName, IConfigurationBuilder builder, IProtocolInfo protocolInfo, IConfigurationReader reader) { if (string.IsNullOrEmpty(hostFileName)) { throw new NullReferenceException(hostFileName); } _hostFile = hostFileName; _protocolInfo = protocolInfo ?? throw new NullReferenceException(nameof(protocolInfo)); _builder = builder ?? throw new NullReferenceException(nameof(builder)); _reader = reader ?? throw new NullReferenceException(nameof(reader)); }
/// <summary> /// 打开包裹得到协议 /// </summary> /// <param name="package"></param> /// <returns></returns> public IProtocolInfo Open(IPackageInfo package) { IProtocolInfo result = null; string WrappedText = package.ToString(); //test Console.WriteLine("WrappedText: {0}", WrappedText); result = DefaultResolver.ToEntity(WrappedText); return(result); }
/// <summary> /// 将协议封装成包裹 /// </summary> /// <param name="protocol"></param> /// <returns></returns> public IPackageInfo Seal(IProtocolInfo protocol) { PackageInfo info = new PackageInfo(); info.Prefix = Encoding.UTF8.GetBytes(PackageSetting.PrefixString); info.BodyEncoding = PackageSetting.Encoding; string protocolPlainText = DefaultResolver.ToText(protocol); info.SetBodyFromString(protocolPlainText); info.BodyLength = BitConverter.GetBytes(Convert.ToInt32(info.Body.Length)); return(info); }
public IProtocolInfo ToEntity(string protocolText) { IProtocolInfo info = null; JObject protocol = JObject.Parse(protocolText.ToLower()); if (protocol != null) { switch (Convert.ToInt32(protocol["cmd"].ToString())) { case 100: info = Deserialize <S2T_HeartbeatInfo>(protocolText); break; case 101: //info = Deserialize<S2T_ChatInfo>(protocolText); break; case 102: //info = Deserialize<S2T_ConnectInfo>(protocolText); break; case 201: info = Deserialize <S2T_ConnectInfo>(protocolText); break; case 202: info = Deserialize <S2T_Catchphrase>(protocolText); break; case 203: break; case 205: { info = Deserialize <S2T_QuizCommit>(protocolText); } break; } } else { Console.WriteLine("未知类型"); } return(info); }
public static void Draw(IProtocolInfo info, Vector2 offset, SpriteFont font, SpriteBatch spriteBatch) { if (!PixelTextures.ContainsKey(spriteBatch)) { var pixelTexture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1, false, SurfaceFormat.Color); pixelTexture.SetData(new[] { Color.White }); PixelTextures[spriteBatch] = pixelTexture; } // Settings. const int graphWidth = 180, graphHeight = 40; // Precompute stuff. int minIncoming = int.MaxValue, maxIncoming = 0, avgIncoming = 0, minOutgoing = int.MaxValue, maxOutgoing = 0, avgOutgoing = 0, minTotal = int.MaxValue, maxTotal = 0, avgTotal = 0; var values = new Tuple <int, Color> [Math.Max(info.IncomingTraffic.Count, info.OutgoingTraffic.Count) - 1][]; for (var i = 0; i < values.Length; ++i) { values[i] = new[] { Tuple.Create(0, Color.White), Tuple.Create(0, Color.White), Tuple.Create(0, Color.White), Tuple.Create(0, Color.White), Tuple.Create(0, Color.White) }; } { // Skip first entry, as that one's subject to change. var i = 1; var incoming = info.IncomingTraffic.First.Next; var outgoing = info.OutgoingTraffic.First.Next; while (i < info.IncomingTraffic.Count && incoming != null && outgoing != null) { var subTotal = 0; { var val = incoming.Value[TrafficTypes.Any]; if (val < minIncoming) { minIncoming = val; } if (val > maxIncoming) { maxIncoming = val; } avgIncoming += val; subTotal += val; values[i - 1][0] = Tuple.Create(incoming.Value[TrafficTypes.Invalid], Color.Firebrick); values[i - 1][1] = Tuple.Create(incoming.Value[TrafficTypes.Protocol], Color.DarkBlue); values[i - 1][2] = Tuple.Create(incoming.Value[TrafficTypes.Data], Color.Blue); } { int val = outgoing.Value[TrafficTypes.Any]; if (val < minOutgoing) { minOutgoing = val; } if (val > maxOutgoing) { maxOutgoing = val; } avgOutgoing += val; subTotal += val; values[i - 1][3] = Tuple.Create(outgoing.Value[TrafficTypes.Protocol], Color.Green); values[i - 1][4] = Tuple.Create(outgoing.Value[TrafficTypes.Data], Color.LimeGreen); } if (subTotal < minTotal) { minTotal = subTotal; } if (subTotal > maxTotal) { maxTotal = subTotal; } avgTotal += subTotal; ++i; incoming = incoming.Next; outgoing = outgoing.Next; } } avgIncoming /= info.HistoryLength - 1; avgOutgoing /= info.HistoryLength - 1; avgTotal /= info.HistoryLength - 1; var netInfo = String.Format( "in: {0}|{1}|{2}|{3:f2}kB/s\n" + " aps: {12:f2}|apc: {13:f2}\n" + "out: {4}|{5}|{6}|{7:f2}kB/s\n" + " aps: {14:f2}|apc: {15:f2}\n" + "sum: {8}|{9}|{10}|{11:f2}kB/s", minIncoming, maxIncoming, avgIncoming, avgIncoming / 1024f, minOutgoing, maxOutgoing, avgOutgoing, avgOutgoing / 1024f, minTotal, maxTotal, avgTotal, avgTotal / 1024f, info.IncomingPacketSizes.Mean(), info.IncomingPacketCompression.Mean(), info.OutgoingPacketSizes.Mean(), info.OutgoingPacketCompression.Mean()); var netInfoMeasure = font.MeasureString(netInfo); var netInfoPosition = offset; var graphPosition = new Vector2(offset.X, offset.Y + netInfoMeasure.Y + 5); var graphNormX = graphWidth / (float)Math.Max(info.IncomingTraffic.Count, info.OutgoingTraffic.Count); var graphNormY = graphHeight / (float)Math.Max(maxTotal, 1); // Draw it. spriteBatch.Begin(); spriteBatch.DrawString(font, netInfo, netInfoPosition, Color.White); // Draw the bars. var barIndex = 0; foreach (var bar in values) { var barX = (int)(graphPosition.X + barIndex * graphNormX); var bottom = graphPosition.Y + graphHeight; foreach (var segment in bar) { if (segment.Item1 <= 0) { continue; } var top = (int)(bottom - segment.Item1 * graphNormY); var line = new Rectangle(barX, top, (int)graphNormX, (int)(bottom - top)); spriteBatch.Draw(PixelTextures[spriteBatch], line, segment.Item2); bottom = top; } ++barIndex; } spriteBatch.End(); }
/// <summary> /// Check for addresses ordering. /// </summary> public static bool IsRange(IReadOnlyCollection <IRegisterGroup> registerGroups, IProtocolInfo info) { var registerInRangeCount = 0; // Already includes first and last registers addresses. int dataSize = 2 * info.AddressSize; int nextAddress = registerGroups.First().Address; foreach (IRegisterGroup registerGroup in registerGroups) { if (dataSize + registerGroup.DataSize > info.MaxDataLength) { break; } foreach (IRegister register in registerGroup.GetRawRegisters()) { if (register.Address != nextAddress) { return(false); } nextAddress++; registerInRangeCount++; } dataSize += registerGroup.DataSize; } if (registerInRangeCount < info.MinimumRangeRegisterCount) { return(false); } return(true); }
public static byte[] ComposeDataAsSeries(IReadOnlyCollection <IRegisterGroup> registerGroups, IProtocolInfo info, IEnumerable <byte> dataHeader, bool withValues, out IReadOnlyCollection <IRegisterGroup> composedGroups) { var result = new List <byte>(dataHeader); var composedGroupList = new List <IRegisterGroup>(); int currentDataPacketSize = result.Count; foreach (IRegisterGroup registerGroup in registerGroups) { int groupSize = GetGroupSizeAsSeries(registerGroup, info); if (currentDataPacketSize + groupSize > info.MaxDataLength) { break; } currentDataPacketSize += groupSize; foreach (IRegister register in registerGroup.GetRawRegisters()) { result.AddRange(GetRegisterAddress(register.Address, info)); if (withValues) { result.AddRange(register.ToBytes()); } } composedGroupList.Add(registerGroup); } composedGroups = composedGroupList; return(result.ToArray()); }
/// <summary> /// Range represent sequence of registers ordered by address in row with structure: /// first register address, last register address, register 1 value, register 2 value, ..., register n value. /// </summary> public static byte[] ComposeDataAsRange(IReadOnlyCollection <IRegisterGroup> registerGroups, IProtocolInfo info, IEnumerable <byte> dataHeader, bool withValues, out IReadOnlyCollection <IRegisterGroup> composedGroups) { var result = new List <byte>(dataHeader); var composedGroupList = new List <IRegisterGroup>(); result.AddRange(GetRegisterAddress(registerGroups.First().Address, info)); int lastRegisterAddressIndex = result.Count; // Temp address should be specified after the packet is formed. result.AddRange(Enumerable.Repeat <byte>(0, info.AddressSize)); // Current packet size with last address. int currentDataPacketSize = result.Count; foreach (IRegisterGroup registerGroup in registerGroups) { if (currentDataPacketSize + registerGroup.DataSize > info.MaxDataLength) { break; } currentDataPacketSize += registerGroup.DataSize; if (withValues) { result.AddRange(registerGroup.ToBytes()); } composedGroupList.Add(registerGroup); } byte[] endRangeAddress = GetRegisterAddress(composedGroupList.Last().GetLastRegisterAddress(), info); foreach (int indexOffset in Enumerable.Range(0, info.AddressSize)) { result[lastRegisterAddressIndex + indexOffset] = endRangeAddress[indexOffset]; } composedGroups = composedGroupList; return(result.ToArray()); }
private static byte[] GetRegisterAddress(int address, IProtocolInfo info) { return(LittleEndianConverter.GetBytes(address, info.AddressSize)); }
private static int GetGroupSizeAsSeries(IRegisterGroup registerGroup, IProtocolInfo info) { return(info.AddressSize + registerGroup.DataSize); }
private static IReadOnlyList <IRegister> ParseAsRange(IReadOnlyList <byte> data, IProtocolInfo info, bool withValues) { // Ignore gByte. int currentByteIndex = info.DataOffset + 1; // Bytes after gByte are a range of addresses. byte startAddress = data[currentByteIndex++]; byte endAddress = data[currentByteIndex++]; int registersCount = endAddress - startAddress + 1; // Check addresses validity. if (startAddress > endAddress) { throw new InvalidRegistersException("Wrong register Address"); } // Check registers count is valid number (less than registerGroup values bytes count). if (withValues && registersCount > data[info.SizeOffset] - info.MinPacketLength - 2) { throw new TooMuchDataRequestedException("Wrong data amount"); } var registers = new List <Register <byte> >(registersCount); foreach (int address in Enumerable.Range(startAddress, registersCount)) { Register <byte> register = withValues ? Register <byte> .CreateByte(address, RegisterType.Raw, data[currentByteIndex++]) : Register <byte> .CreateByte(address, RegisterType.Raw); registers.Add(register); } return(registers); }
private static IReadOnlyList <IRegister> ParseAsSeries(IReadOnlyList <byte> data, IProtocolInfo info, bool withValues) { // Look through all data bytes except CRC. byte packetSize = data[info.SizeOffset]; int byteIndex = info.MinPacketLength; var registers = new List <Register <byte> >(); if (withValues) { while (byteIndex < packetSize - 1) { registers.Add(Register <byte> .CreateByte(data[byteIndex++], RegisterType.Raw, data[byteIndex++])); } } else { while (byteIndex < packetSize - 1) { registers.Add(Register <byte> .CreateByte(data[byteIndex++], RegisterType.Raw)); } } // Case of crc is register value. if (byteIndex != packetSize - 1) { throw new Exception("Wrong data amount"); } return(registers); }
public string ToText(IProtocolInfo info) { return(JsonConvert.SerializeObject(info)); }
/// <summary> /// 验证学生 /// </summary> /// <param name="e"></param> /// <param name="info"></param> private static bool DoFirstValidation(ClientStateEventArgs e, IProtocolInfo info) { S2T_ConnectInfo connectInfo = info as S2T_ConnectInfo; // 新的客户端 var ThisClient = e.ClientProxy; // 新的学生编号 var ThisBusinessId = connectInfo.msg.sId; // 全局的学生清单 var StudentDevices = ServerManager.StudentDevices; lock (StudentDevices) { // 查询学生清单中是否存在对应编号的学生 Student key = StudentDevices.Keys.FirstOrDefault(p => p.StudentBusinessId == ThisBusinessId); if (key != null) { var ValueClient = StudentDevices[key]; if (ValueClient == null) { // 如果不存在,则关联学生对象和客户端对象 StudentDevices[key] = ThisClient; ThisClient.BusinessID = key.StudentBusinessId; // 关联业务ID,以便下次作比较 // 2019-04-16 mzc //e.BusinessId = ThisBusinessId; key.IsOnline = true; Console.WriteLine($"学生{key.RealName}连接上了"); } else { // 如果已存在,判断客户端列表里是否有相同ID的连接(比较业务ID,如果相同,则断开之前的连接) if (ValueClient.BusinessID.ToDefaultString() == ThisBusinessId) { var lastClient = StudentDevices[key]; //todo: 改为发命令 //ServerManager.Recycle(lastClient.ReceiveContext); Console.WriteLine("同一学生重复连接,回收之前的一个连接,并保留当前连接。"); } StudentDevices[key] = ThisClient; ThisClient.BusinessID = key.StudentBusinessId; key.IsOnline = true; // 2019-04-16 mzc //e.BusinessId = ThisBusinessId; } return(true); } else { // 如果连接上来的不是该班级的学生,则断开连接 ServerManager.Recycle(e.ClientSocketContext); return(false); } } }