Example #1
0
        /// <summary>
        /// UDP打洞过程
        /// 假设A想连接B.首先A发送打洞消息给Server,让Server告诉B有人想与你建立通话通道,Server将A的IP信息转发给B
        /// B收到命令后向A发一个UDP包,此时B的NAT会建立一个与A通讯的Session. 然后A再次向B发送UDP包B就能收到了
        /// </summary>
        public void HolePunching(User user)
        {
            //A:自己; B:参数user
            //A发送打洞消息给服务器,请求与B打洞
            C2S_HolePunchingRequestMessage msg = new C2S_HolePunchingRequestMessage(_LocalUserName, user.UserName);

            this.SendMessage(msg, _hostPoint);

            Thread.Sleep(2000);//等待对方发送UDP包并建立Session

            //再向对方发送确认消息,如果对方收到会发送一个P2P_HolePunchingResponse确认消息,此时打洞成功
            P2P_HolePunchingTestMessage confirmMessage = new P2P_HolePunchingTestMessage(_LocalUserName);

            this.SendMessage(confirmMessage, user);
        }
Example #2
0
        //运行线程
        private void Run()
        {
            try
            {
                byte[] buffer;//接受数据用
                while (true)
                {
                    buffer = _client.Receive(ref _remotePoint);//_remotePoint变量返回当前连接的用户IP地址

                    object msgObj  = ObjectSerializer.Deserialize(buffer);
                    Type   msgType = msgObj.GetType();
                    DoWriteLog("接收到消息:" + msgType.ToString() + " From:" + _remotePoint.ToString());

                    if (msgType == typeof(S2C_UserListMessage))
                    {
                        // 更新用户列表
                        S2C_UserListMessage usersMsg = (S2C_UserListMessage)msgObj;
                        _userList.Clear();

                        foreach (User user in usersMsg.UserList)
                        {
                            _userList.Add(user);
                        }

                        this.DisplayUsers(_userList);
                    }
                    else if (msgType == typeof(S2C_UserAction))
                    {
                        //用户动作,新用户登录/用户登出
                        S2C_UserAction msgAction = (S2C_UserAction)msgObj;
                        if (msgAction.Action == UserAction.Login)
                        {
                            _userList.Add(msgAction.User);
                            this.DisplayUsers(_userList);
                        }
                        else if (msgAction.Action == UserAction.Logout)
                        {
                            User user = _userList.Find(msgAction.User.UserName);
                            if (user != null)
                            {
                                _userList.Remove(user);
                            }
                            this.DisplayUsers(_userList);
                        }
                    }
                    else if (msgType == typeof(S2C_HolePunchingMessage))
                    {
                        //接受到服务器的打洞命令
                        S2C_HolePunchingMessage msgHolePunching = (S2C_HolePunchingMessage)msgObj;

                        //NAT-B的用户给NAT-A的用户发送消息,此时UDP包肯定会被NAT-A丢弃,
                        //因为NAT-A上并没有A->NAT-B的合法Session, 但是现在NAT-B上就建立了有B->NAT-A的合法session了!
                        P2P_HolePunchingTestMessage msgTest = new P2P_HolePunchingTestMessage(_LocalUserName);
                        this.SendMessage(msgTest, msgHolePunching.RemotePoint);
                    }
                    else if (msgType == typeof(P2P_HolePunchingTestMessage))
                    {
                        //UDP打洞测试消息
                        //_HoleAccepted = true;
                        P2P_HolePunchingTestMessage msgTest = (P2P_HolePunchingTestMessage)msgObj;
                        UpdateConnection(msgTest.UserName, _remotePoint);

                        //发送确认消息
                        P2P_HolePunchingResponse response = new P2P_HolePunchingResponse(_LocalUserName);
                        this.SendMessage(response, _remotePoint);
                    }
                    else if (msgType == typeof(P2P_HolePunchingResponse))
                    {
                        //_HoleAccepted = true;//打洞成功
                        P2P_HolePunchingResponse msg = msgObj as P2P_HolePunchingResponse;
                        UpdateConnection(msg.UserName, _remotePoint);
                    }
                    else if (msgType == typeof(P2P_TalkMessage))
                    {
                        //用户间对话消息
                        P2P_TalkMessage workMsg = (P2P_TalkMessage)msgObj;
                        DoWriteLog(workMsg.Message);
                    }
                    else
                    {
                        DoWriteLog("收到未知消息!");
                    }
                }
            }
            catch (Exception ex) { DoWriteLog(ex.Message); }
        }