private async void Run() { byte[] buffer; while (true) { buffer = await client.Receive(remotePoint); object msgObj = FormatterHelper.Deserialize(buffer); Type msgType = msgObj.GetType(); if (msgType == typeof(ListUserResponseMessage)) { // 转换消息 ListUserResponseMessage usersMsg = (ListUserResponseMessage)msgObj; // 更新用户列表 userList.Clear(); foreach (User user in usersMsg.UserList) { userList.Add(user); } this.DisplayUsers(userList); } else if (msgType == typeof(PingMessage)) { // 转换消息 PingMessage purchReqMsg = (PingMessage)msgObj; // 发送打洞消息到远程主机 TrashMessage trashMsg = new TrashMessage(); buffer = FormatterHelper.Serialize(trashMsg); client.Send(buffer, buffer.Length, purchReqMsg.RemotePoint); } else if (msgType == typeof(P2PTextMessage)) { // 转换消息 P2PTextMessage workMsg = (P2PTextMessage)msgObj; Console.WriteLine("Receive a message: {0}", workMsg.Message); // 发送应答消息 P2PAckMessage ackMsg = new P2PAckMessage(); buffer = FormatterHelper.Serialize(ackMsg); client.Send(buffer, buffer.Length, remotePoint); } else if (msgType == typeof(P2PAckMessage)) { this.ReceivedACK = true; } else if (msgType == typeof(TrashMessage)) { Console.WriteLine("Recieve a trash message"); } Thread.Sleep(100); } }
/// <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); }
/// <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; }