![]()
2. P2Pserver
namespace P2P.P2PServer
{
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using P2P.WellKnown;
/// <summary>
/// AppClass 的摘要说明。
/// </summary>
public class AppClass
{
public static void Main()
{
Server server = new Server();
try
{
server.Start();
Console.ReadLine();
server.Stop();
}
catch
{
}
}
}
/// <summary>
/// Server 的摘要说明。
/// </summary>
public class Server
{
private UdpClient server;
private UserCollection userList;
private Thread serverThread;
private IPEndPoint remotePoint;
public Server()
{
userList = new UserCollection();
remotePoint = new IPEndPoint(IPAddress.Any, 0);
serverThread = new Thread(new ThreadStart(Run));
}
public void Start()
{
try
{
server = new UdpClient(P2PConsts.SRV_PORT);
serverThread.Start();
Console.WriteLine("P2P Server started, waiting client connect...");
}
catch(Exception exp)
{
Console.WriteLine("Start P2P Server error: " + exp.Message);
throw exp;
}
}
public void Stop()
{
Console.WriteLine("P2P Server stopping...");
try
{
serverThread.Abort();
server.Close();
Console.WriteLine("Stop OK.");
}
catch(Exception exp)
{
Console.WriteLine("Stop error: " + exp.Message);
throw exp;
}
}
private void Run()
{
byte[] buffer = null;
while (true)
{
byte[] msgBuffer = server.Receive(ref remotePoint);
try
{
object msgObj = FormatterHelper.Deserialize(msgBuffer);
Type msgType = msgObj.GetType();
if (msgType == typeof(P2P.WellKnown.C2S.LoginMessage))
{
// 转换接受的消息
P2P.WellKnown.C2S.LoginMessage lginMsg = (P2P.WellKnown.C2S.LoginMessage)msgObj;
Console.WriteLine("has an user login: {0}", lginMsg.UserName);
// 添加用户到列表
IPEndPoint userEndPoint = new IPEndPoint(remotePoint.Address, remotePoint.Port);
User user = new User(lginMsg.UserName, userEndPoint);
userList.Add(user);
// 发送应答消息
P2P.WellKnown.S2C.GetUsersResponseMessage usersMsg = new P2P.WellKnown.S2C.GetUsersResponseMessage(userList);
buffer = FormatterHelper.Serialize(usersMsg);
server.Send(buffer, buffer.Length, remotePoint);
}
else if (msgType == typeof(P2P.WellKnown.C2S.LogoutMessage))
{
// 转换接受的消息
P2P.WellKnown.C2S.LogoutMessage lgoutMsg = (P2P.WellKnown.C2S.LogoutMessage)msgObj;
Console.WriteLine("has an user logout: {0}", lgoutMsg.UserName);
// 从列表中删除用户
User lgoutUser = userList.Find(lgoutMsg.UserName);
if (lgoutUser != null)
{
userList.Remove(lgoutUser);
}
}
else if (msgType == typeof(P2P.WellKnown.C2S.TranslateMessage))
{
// 转换接受的消息
P2P.WellKnown.C2S.TranslateMessage transMsg = (P2P.WellKnown.C2S.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
{
P2P.WellKnown.S2C.SomeOneCallYouMessage transMsg2 = new P2P.WellKnown.S2C.SomeOneCallYouMessage(remotePoint);
buffer = FormatterHelper.Serialize(transMsg);
server.Send(buffer, buffer.Length, toUser.NetPoint);
}
}
else if (msgType == typeof(P2P.WellKnown.C2S.GetUsersMessage))
{
// 发送当前用户信息到所有登录客户
P2P.WellKnown.S2C.GetUsersResponseMessage srvResMsg = new P2P.WellKnown.S2C.GetUsersResponseMessage(userList);
buffer = FormatterHelper.Serialize(srvResMsg);
foreach(User user in userList)
{
server.Send(buffer, buffer.Length, user.NetPoint);
}
}
Thread.Sleep(500);
}
catch{}
}
}
}
}
3. P2Pclient
namespace P2P.P2PClient
{
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using P2P.WellKnown;
///
<summary>
/// AppClass 的摘要说明。
///
</summary>
public class AppClass
{
public static void Main()
{
Client client = new Client("202.96.134.103");
client.ConnectToServer("myname", "mypassword");
client.Start();
Console.WriteLine("test arguments");
while (true)
{
string str = Console.ReadLine();
client.PaserCommand(str);
}
}
}
/// <summary>
/// Client 的摘要说明。
/// </summary>
public class Client : IDisposable
{
private const int MAXRETRY = 10;
private UdpClient client;
private IPEndPoint hostPoint;
private IPEndPoint remotePoint;
private UserCollection userList;
private string myName;
private bool ReceivedACK;
private Thread listenThread;
public Client(string serverIP)
{
ReceivedACK = false;
remotePoint = new IPEndPoint(IPAddress.Any, 0);
hostPoint = new IPEndPoint(IPAddress.Parse(serverIP), P2PConsts.SRV_PORT);
client = new UdpClient();
userList = new UserCollection();
listenThread = new Thread(new ThreadStart(Run));
}
public void Start()
{
if (this.listenThread.ThreadState==ThreadState.Unstarted)
{
this.listenThread.Start();
Console.WriteLine("You can input you command:"n");
Console.WriteLine("Command Type:""send"",""exit"",""getu""");
Console.WriteLine("Example : send Username Message");
Console.WriteLine("
exit");
Console.WriteLine("
getu");
}
}
public void ConnectToServer(string userName, string password)
{
myName = userName;
// 发送登录消息到服务器
P2P.WellKnown.C2S.LoginMessage lginMsg = new P2P.WellKnown.C2S.LoginMessage(userName, password);
byte[] buffer = FormatterHelper.Serialize(lginMsg);
client.Send(buffer, buffer.Length, hostPoint);
// 接受服务器的登录应答消息
buffer = client.Receive(ref remotePoint);
P2P.WellKnown.S2C.GetUsersResponseMessage srvResMsg = (P2P.WellKnown.S2C.GetUsersResponseMessage)FormatterHelper.Deserialize(buffer);
// 更新用户列表
userList.Clear();
foreach(User user in srvResMsg.UserList)
{
userList.Add(user);
}
this.DisplayUsers(userList);
}
/// <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++)
{
P2P.WellKnown.P2P.WorkMessage workMsg = new P2P.WellKnown.P2P.WorkMessage(message);
byte[] buffer = FormatterHelper.Serialize(workMsg);
相关文章:
猜你喜欢
-
2022-12-23
-
2021-11-22
-
2022-02-12
相关资源
-
下载
2021-07-01
-
下载
2021-06-06
-
下载
2023-01-14
-
下载
2022-12-02