/// <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); SendMessage(msg, _hostPoint); Thread.Sleep(2000);//等待对方发送UDP包并建立Session //再向对方发送确认消息,如果对方收到会发送一个P2P_HolePunchingResponse确认消息,此时打洞成功 P2P_HolePunchingTestMessage confirmMessage = new P2P_HolePunchingTestMessage(_LocalUserName); SendMessage(confirmMessage, user); }
public void SendMessage(MessageBase msg, User user) { SendMessage(msg, user.NetPoint); }
//线程主方法 private void Run() { byte[] msgBuffer; while (true) { msgBuffer = _server.Receive(ref _remotePoint); //接受消息 try { //将消息转换为对象 object msgObject = ObjectSerializer.Deserialize(msgBuffer); if (msgObject == null) continue; Type msgType = msgObject.GetType(); DoWriteLog("接收到消息:" + msgType); DoWriteLog("From:" + _remotePoint); //新用户登录 if (msgType == typeof(C2S_LoginMessage)) { var lginMsg = (C2S_LoginMessage)msgObject; DoWriteLog(string.Format("用户’{0}’已登录!", lginMsg.FromUserName)); // 添加用户到列表 var userEndPoint = new IPEndPoint(_remotePoint.Address, _remotePoint.Port); var user = new User(lginMsg.FromUserName, userEndPoint); _userList.Add(user); DoUserChanged(_userList); //通知所有人,有新用户登录 var msgNewUser = new S2C_UserAction(user, UserAction.Login); foreach (User u in _userList) { if (u.UserName == user.UserName) //如果是自己,发送所有在线用户列表 SendMessage(new S2C_UserListMessage(_userList), u.NetPoint); else SendMessage(msgNewUser, u.NetPoint); } } else if (msgType == typeof(C2S_LogoutMessage)) { var lgoutMsg = (C2S_LogoutMessage)msgObject; DoWriteLog(string.Format("用户’{0}’已登出!", lgoutMsg.FromUserName)); // 从列表中删除用户 User logoutUser = _userList.Find(lgoutMsg.FromUserName); if (logoutUser != null) _userList.Remove(logoutUser); DoUserChanged(_userList); //通知所有人,有用户登出 var msgNewUser = new S2C_UserAction(logoutUser, UserAction.Logout); foreach (User u in _userList) SendMessage(msgNewUser, u.NetPoint); } else if (msgType == typeof(C2S_HolePunchingRequestMessage)) { //接收到A给B打洞的消息,打洞请求,由客户端发送给服务器端 var msgHoleReq = (C2S_HolePunchingRequestMessage)msgObject; User userA = _userList.Find(msgHoleReq.FromUserName); User userB = _userList.Find(msgHoleReq.ToUserName); // 发送打洞(Punching Hole)消息 DoWriteLog(string.Format("用户:[{0} IP:{1}]想与[{2} IP:{3}]建立对话通道.", userA.UserName, userA.NetPoint, userB.UserName, userB.NetPoint)); //由Server发送消息给B,将A的IP的IP地址信息告诉B,然后由B发送一个测试消息给A. var msgHolePunching = new S2C_HolePunchingMessage(_remotePoint); SendMessage(msgHolePunching, userB.NetPoint); //Server->B } else if (msgType == typeof(C2S_GetUsersMessage)) { // 发送当前用户信息 var srvResMsg = new S2C_UserListMessage(_userList); SendMessage(srvResMsg, _remotePoint); } } catch (Exception ex) { DoWriteLog(ex.Message); } } }
public void Remove(User user) { InnerList.Remove(user); }
public void Add(User user) { InnerList.Add(user); }
public S2C_UserAction(User user, UserAction action) { _User = user; _Action = action; }