Exemplo n.º 1
0
        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);
            }
        }
Exemplo n.º 2
0
 private void Client_MessageArrive(object sender, MessageArriveArgs e)
 {
     Console.WriteLine("[C] Received: " + Encoding.UTF8.GetString(e.Content.Array, e.Content.Offset, e.Content.Count));
 }
Exemplo n.º 3
0
        /// <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++;
                    }
                }
            }
        }
Exemplo n.º 4
0
        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]);
                }
            }
        }
Exemplo n.º 5
0
 /// <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);
 }
Exemplo n.º 6
0
        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;
            }
        }