/// <summary> /// 这是主要的函数:发送一个消息给某个用户(C) /// 流程:直接向某个用户的外网IP发送消息,如果此前没有联系过 /// 那么此消息将无法发送,发送端等待超时。 /// 超时后,发送端将发送一个请求信息到服务端,要求服务端发送 /// 给客户C一个请求,请求C给本机发送打洞消息 /// 以上流程将重复MAXRETRY次 /// </summary> /// <param name="toUserName">对方用户名</param> /// <param name="message">待发送的消息</param> /// <returns></returns> private bool SendMessageTo(string toUserName, string message) { User toUser = userList.Find(toUserName); if (toUser == null) { return(false); } for (int i = 0; i < MAXRETRY; i++) { P2PTextMessage workMsg = new P2PTextMessage(message); byte[] buffer = FormatterHelper.Serialize(workMsg); client.Send(buffer, buffer.Length, toUser.NetPoint); // 等待接收线程将标记修改 for (int j = 0; j < 10; j++) { if (this.ReceivedACK) { this.ReceivedACK = false; return(true); } else { Thread.Sleep(300); } } // 没有接收到目标主机的回应,认为目标主机的端口映射没有 // 打开,那么发送请求信息给服务器,要服务器告诉目标主机 // 打开映射端口(UDP打洞) TranslateMessage transMsg = new TranslateMessage(myName, toUserName); buffer = FormatterHelper.Serialize(transMsg); client.Send(buffer, buffer.Length, hostPoint); // 等待对方先发送信息 Thread.Sleep(100); } return(false); }
private async void Run() { byte[] buffer = null; while (true) { byte[] msgBuffer = await server.Receive(remotePoint); try { object msgObj = FormatterHelper.Deserialize(msgBuffer); Type msgType = msgObj.GetType(); if (msgType == typeof(LoginMessage)) { // 转换接受的消息 LoginMessage lginMsg = (LoginMessage)msgObj; Console.WriteLine("{0}: user {1} sign in.", System.DateTime.Now.ToString(), lginMsg.UserName); // 添加用户到列表 IPEndPoint userEndPoint = new IPEndPoint(remotePoint.Address, remotePoint.Port); User user = new User(lginMsg.UserName, userEndPoint); userList.Add(user); // 发送应答消息 ListUserResponseMessage usersMsg = new ListUserResponseMessage(userList); buffer = FormatterHelper.Serialize(usersMsg); server.Send(buffer, buffer.Length, remotePoint); Console.WriteLine("Send:" + usersMsg); } else if (msgType == typeof(LogoutMessage)) { // 转换接受的消息 LogoutMessage lgoutMsg = (LogoutMessage)msgObj; Console.WriteLine("{0}: {1} sign out", System.DateTime.Now.ToString(), lgoutMsg.UserName); // 从列表中删除用户 User lgoutUser = userList.Find(lgoutMsg.UserName); if (lgoutUser != null) { userList.Remove(lgoutUser); } } else if (msgType == typeof(TranslateMessage)) { // 转换接受的消息 TranslateMessage transMsg = (TranslateMessage)msgObj; Console.WriteLine("{0}(1) wants to p2p {2}", remotePoint.Address.ToString(), transMsg.UserName, transMsg.ToUserName); // 获取目标用户 User toUser = userList.Find(transMsg.ToUserName); // 转发Purch Hole请求消息 if (toUser == null) { Console.WriteLine("Remote host {0} cannot be found at index server", transMsg.ToUserName); } else { PingMessage transMsg2 = new PingMessage(remotePoint); buffer = FormatterHelper.Serialize(transMsg); server.Send(buffer, buffer.Length, toUser.NetPoint); Console.WriteLine("Send:" + transMsg2); } } else if (msgType == typeof(ListUserMessage)) { // 发送当前用户信息到所有登录客户 ListUserResponseMessage srvResMsg = new ListUserResponseMessage(userList); buffer = FormatterHelper.Serialize(srvResMsg); foreach (User user in userList.InnerList) { server.Send(buffer, buffer.Length, user.NetPoint); Console.WriteLine("Send:" + srvResMsg); } } Thread.Sleep(500); } catch (Exception e) { System.Console.WriteLine(e.Message); System.Console.WriteLine(e.StackTrace); } } }