private static void Server_MessageArrive(object sender, MessageArriveArgs e) { Console.WriteLine("[S] Received: " + Encoding.UTF8.GetString(e.Content.Array, e.Content.Offset, e.Content.Count)); // 如果是收到的第一个消息,则开始加密 if (!e.Session.IsEncrypted) { var splited = Encoding.UTF8.GetString(e.Content.Array, e.Content.Offset, e.Content.Count).Split('*'); e.Session.AesIV = Convert.FromBase64String(splited[0]); e.Session.AesKey = Convert.FromBase64String(splited[1]); e.Session.IsEncrypted = true; e.Session.Send(e.Content.Array, 0, e.Content.Count, replyToMessage: e); } else { var p = int.Parse(Encoding.UTF8.GetString(e.Content.Array, e.Content.Offset, e.Content.Count)); var dataHello = Encoding.UTF8.GetBytes((p * p).ToString()); e.Session.Send(dataHello, 0, dataHello.Length, replyToMessage: e); } }
private void Client_MessageArrive(object sender, MessageArriveArgs e) { Console.WriteLine("[C] Received: " + Encoding.UTF8.GetString(e.Content.Array, e.Content.Offset, e.Content.Count)); }
/// <summary> /// 向远端发送数据。 /// </summary> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="count"></param> internal ArraySegment<byte>? Send(byte[] data, int offset, int count, MessageArriveArgs replyToMessage = null, Action<ArraySegment<byte>> replyCallback = null, bool block = false, MessageFlags extraFlags = MessageFlags.None) { if (socket == null) throw new Exception("连接已经断开或尚未打开"); if (replyToMessage != null && replyToMessage.HasReplied) throw new Exception("不能重复回复消息"); if (data == null) throw new ArgumentNullException(nameof(data)); if (offset < 0 || offset >= data.Length) throw new ArgumentOutOfRangeException(nameof(offset)); if (count <= 0 || offset + count > data.Length) throw new ArgumentOutOfRangeException(nameof(count)); if (replyCallback != null && replyToMessage != null) throw new ArgumentException("回复消息时不能再接受回复"); if (block && replyToMessage != null) throw new ArgumentException("回复消息时不能再接受回复"); if (block && replyCallback != null) throw new ArgumentException("使用阻塞模式时不能设置 callback"); lock (lockerSend) { try { MessageFlags flags = MessageFlags.None | extraFlags; short mid; if (replyToMessage != null) { flags |= MessageFlags.Response; mid = replyToMessage.MessageID; } else { flags |= MessageFlags.Request; mid = currentMessageID; } // 获取正文 ArraySegment<byte> contentToSend; if (IsEncrypted == false) { contentToSend = new ArraySegment<byte>(data, offset, count); } else { // 加密要发送的数据 initEncryption(); contentToSend = new ArraySegment<byte>(aesEncoder.TransformFinalBlock(data, offset, count)); } BitConverter.GetBytes(System.Net.IPAddress.HostToNetworkOrder(contentToSend.Count + 4)).CopyTo(headerBuffer, 0); BitConverter.GetBytes(System.Net.IPAddress.HostToNetworkOrder((short)flags)).CopyTo(headerBuffer, 4); BitConverter.GetBytes(System.Net.IPAddress.HostToNetworkOrder(mid)).CopyTo(headerBuffer, 6); // 如果带有 callback,则进行处理 if (replyCallback != null || block) { if (this.waitHandles[mid] == null) { this.waitHandles[mid] = new object(); } if (replyCallback != null) { ThreadPool.QueueUserWorkItem(o => { var id = (short)o; lock (waitHandles[id]) { if (Monitor.Wait(waitHandles[id], ReceiveReplyTimeout)) { replyCallback(this.replyArrays[id]); replyArrays[id] = new ArraySegment<byte>(); // 清理内存 } } }, mid); } } try { socket.Send(new ArraySegment<byte>[] { new ArraySegment<byte>(headerBuffer), contentToSend }); } catch { closeSocket(); throw new Exception("连接已经断开"); } // 如果是阻塞模式,则等待 if (block) { lock (waitHandles[mid]) { if (Monitor.Wait(waitHandles[mid], ReceiveReplyTimeout)) { var ret = replyArrays[mid]; replyArrays[mid] = new ArraySegment<byte>(); // 清理内存 return ret; } } throw new TimeoutException("等待远端回复超时。"); } return null; } finally { if (replyToMessage == null) { if (currentMessageID == short.MaxValue - 1) currentMessageID = 0; else currentMessageID++; } } } }
private void processData(byte[] receivedData, int offset, int length) { // 获取消息的基本属性 var flags = (MessageFlags)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(receivedData, offset)); var mid = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(receivedData, offset + sizeof(short))); // 将正文消息封装给客户端处理,并允许客户端回复 var buffer = new byte[length - 4]; Array.Copy(receivedData, offset + 4, buffer, 0, length - 4); if (IsEncrypted) { // 如果此消息被加密,则解密 initEncryption(); buffer = aes.CreateDecryptor().TransformFinalBlock(buffer, 0, buffer.Length); } if ((flags & MessageFlags.Request) == MessageFlags.Request) { // 对于请求,调用用户的相关功能 var arg = new MessageArriveArgs(null, mid, buffer, 0, buffer.Length); if (MessageArrive != null) { ThreadPool.QueueUserWorkItem(o => { waitHandle.WaitOne(); try { MessageArrive(this, arg); } catch { } finally { waitHandle.Set(); } }); } } else { // 对于回复消息,触发相关的事件 if (waitHandles[mid] != null) { replyArrays[mid] = new ArraySegment<byte>(buffer); lock (waitHandles[mid]) Monitor.Pulse(waitHandles[mid]); } } }
/// <summary> /// 向远端发送数据。 /// </summary> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="count"></param> public ArraySegment<byte>? Send(byte[] data, int offset, int count, MessageArriveArgs replyToMessage = null, Action<ArraySegment<byte>> replyCallback = null, bool block = false) { return Send(data, offset, count, replyToMessage, replyCallback, block, MessageFlags.None); }
private bool ProcessData(TcpServerUserSession session, byte[] receivedData, int offset, int length) { try { // 首先读取头部信息,以确定所传输的数据特征 var flags = (MessageFlags)(System.Net.IPAddress.NetworkToHostOrder(BitConverter.ToInt16(receivedData, offset))); var isReply = (flags & MessageFlags.Response) == MessageFlags.Response; // 获取消息号 var messageID = System.Net.IPAddress.NetworkToHostOrder(BitConverter.ToInt16(receivedData, offset + sizeof(short))); // 进行处理,将数据拷贝以防止缓冲区覆盖 var buffer = new byte[length - sizeof(short) * 2]; Array.Copy(receivedData, offset + sizeof(short) * 2, buffer, 0, buffer.Length); if (session.IsEncrypted) { // 对于已经加密的内容,要进行解密 session.initEncryption(); buffer = session.aes.CreateDecryptor().TransformFinalBlock(buffer, 0, buffer.Length); } if (!isReply) { var args = new MessageArriveArgs(session, messageID, buffer, 0, buffer.Length); if ((flags & MessageFlags.InternalCalls) == MessageFlags.InternalCalls) { // 如果是内部指令,可以直接在内部处理 if (buffer[0] == (byte)InternalCalls.RequestRSAPublicKey) { // 发送 RSA 公钥 session.SendAndForget(Encoding.UTF8.GetBytes(rsa.ToXmlString(false)), args); } else if (buffer[0] == (byte)InternalCalls.SendAESKeysViaRSA) { if (rsa == null) { session.SendAndForget(new byte[] { 1 }, args); } else { // 解析 AES Key 和 IV,然后开始加密对话 var aesKeyAndIV = rsa.Decrypt(buffer.Skip(1).ToArray(), true); session.AesKey = aesKeyAndIV.Take(16).ToArray(); session.AesIV = aesKeyAndIV.Skip(16).Take(16).ToArray(); session.SendAndForget(new byte[] { 0 }, args); session.IsEncrypted = true; } } } else { ThreadPool.QueueUserWorkItem(o => { maxCountOfConcurrentDataProccesserLimiter.WaitOne(); try { if (this.MessageArrive != null) { MessageArrive(this, args); } } catch { session.Dispose(); } finally { maxCountOfConcurrentDataProccesserLimiter.Release(); } }); } return true; } else { // 对于回复,首先判断是否有等待的句柄 if (session.waitHandles[messageID] == null) return true; // 设置参数 session.replyArrays[messageID] = new ArraySegment<byte>(buffer, 0, buffer.Length); // 如果有等待句柄,则通知事件 lock (session.waitHandles[messageID]) Monitor.Pulse(session.waitHandles[messageID]); return true; } } catch { return false; } }