udp打洞java_UDP打洞原理及代码

本文介绍了如何使用Java实现UDP打洞技术,包括创建UDPP2P套接字管理类,处理用户登录、消息传递、服务器创建和客户端创建等过程,并提供了打洞线程和打洞请求的处理方法。
摘要由CSDN通过智能技术生成

//UDPP2PSock.cs

usingSystem;usingSystem.Collections.Generic;usingSystem.Text;usingSystem.Net;usingSystem.Net.Sockets;usingSystem.Threading;usingP2PWellKnown;namespaceUDPP

{///

///UDPP2P套接字管理类///

public classUDPP2PSock

{///

///用户登录事件///

public eventUdpUserLogInDelegate OnUserLogInU;///

///一般UDP消息事件///

public eventUdpMessageDelegate OnSockMessageU;///

///初始化一个新连接事件///

public eventUdpNewConnectDelegate OnNewConnectU;///

///UDP服务器///

privateUdpClient m_udpServer;///

///UDP客户端///

privateUdpClient m_udpClient;///

///服务器实际上在本地机器上监听的///端口,用于当一台计算机上同时启///动两个可两以上服务器进程时,标///识不同的服务器进程///

private intm_iMyServerPort;///

///客户端在本地机器上实际使用的端口,///用于当一台计算机上同时有两个或两///个以上客户端进程在运行时,标识不///同的客户端进程///

private intm_iMyClientPort;///

///标识是否已成功创服务器///

private boolm_bServerCreated;///

///标识是否已成功创建客户端///

private boolm_bClientCreated;///

///服务器使用的线程///

privateThread m_serverThread;///

///客户端使用的线程///

privateThread m_clientThread;///

///打洞线程///

//private Thread m_burrowThread;

///

///远端节点///

privateIPEndPoint m_remotePoint;///

///当前进程作为客户端的公共终端///

private stringm_strMyPublicEndPoint;///

///当前进程作为客户端的私有终端///

private stringm_strMyPrivateEndPoint;///

///用于接受信息的 StringBuilder实例///

private StringBuilder m_sbResponse = newStringBuilder();///

///P2P打洞时标识是否收到回应消息///

private bool m_bRecvAck = false;///

///请求向其方向打洞的私有终端///

privateIPEndPoint m_requestPrivateEndPoint;///

///请求向其方向打洞的公共终端///

privateIPEndPoint m_requestPublicEndPoint;///

///打洞消息要发向的节点///

privateToEndPoint m_toEndPoint;///

///用于标识是否已经和请求客户端建立点对连接///

//private bool m_bHasConnected=false ;

///

///创建服务器或客户端的最大尝试///次数,为(65536-60000),防止///因不能创建而限入死循环或使用///无效端口///

private const int MAX_CREATE_TRY = 5536;///

///打洞时尝试连接的最大尝试次数///

private const int MAX_CONNECT_TRY = 10;///

///构造函数,初始化UDPP2P实例///

publicUDPP2PSock()

{

m_iMyServerPort=P2PConsts.UDP_SRV_PORT;

m_iMyClientPort= 60000;

m_bClientCreated= false;

m_bServerCreated= false;

m_toEndPoint= newToEndPoint();

m_serverThread= new Thread(newThreadStart(RunUDPServer));

m_clientThread= new Thread(newThreadStart(RunUDPClient));//m_burrowThread = new Thread(new ThreadStart(BurrowProc));

}///

///创建UDP 服务器///

public voidCreateUDPSever()

{int iTryNum = 0;//开始尝试创建服务器

while (!m_bServerCreated && iTryNum

{try{

m_udpServer= newUdpClient(m_iMyServerPort);

m_bServerCreated= true;

}catch{

m_iMyServerPort++;

iTryNum++;

}

}//创建失败,抛出异常

if (!m_bServerCreated && iTryNum ==MAX_CREATE_TRY)

{throw new Exception("创建服务器尝试失败!");

}

m_serverThread.Start();

}///

///创建UDP客户端///

///

///

public void CreateUDPClient(string strServerIP, intiServerPort)

{int iTryNum = 0;//开始尝试创建服务器

while (!m_bClientCreated && iTryNum

{try{

m_udpClient= newUdpClient(m_iMyClientPort);

m_bClientCreated= true;string strIPAddress = (System.Net.Dns.GetHostAddresses("localhost")[0]).ToString();

m_strMyPrivateEndPoint= strIPAddress + ":" +m_iMyClientPort.ToString();

}catch{

m_iMyClientPort++;

iTryNum++;

}

}//创建失败,抛出异常

if (!m_bClientCreated && iTryNum ==MAX_CREATE_TRY)

{throw new Exception("创建客户端尝试失败!");

}

IPEndPoint hostPoint= newIPEndPoint(IPAddress.Parse(strServerIP), iServerPort);string strLocalIP = (System.Net.Dns.GetHostAddresses("localhost"))[0].ToString();

SendLocalPoint(strLocalIP, m_iMyClientPort, hostPoint);

m_clientThread.Start();

}///

///运行UDP 服务器///

private voidRunUDPServer()

{while (true)

{byte[] msgBuffer = m_udpServer.Receive(refm_remotePoint);

m_sbResponse.Append(System.Text.Encoding.Default.GetString(msgBuffer));

CheckCommand();

Thread.Sleep(10);

}

}///

///运行UDP客户端///

private voidRunUDPClient()

{while (true)

{byte[] msgBuffer = m_udpClient.Receive(refm_remotePoint);

m_sbResponse.Append(System.Text.Encoding.Default.GetString(msgBuffer));

CheckCommand();

Thread.Sleep(10);

}

}///

///销毁UDP 服务器///

public voidDisposeUDPServer()

{

m_serverThread.Abort();

m_udpServer.Close();

}///

///销毁UDP客房端///

public voidDisposeUDPClient()

{

m_clientThread.Abort();

m_udpClient.Close();

}///

///发送消息///

///

///

public void SendData(stringstrMsg, IPEndPoint REP)

{byte[] byMsg =System.Text.Encoding.Default.GetBytes(strMsg.ToCharArray());

m_udpClient.Send(byMsg, byMsg.Length, REP);

}///

///发送消息,服务器专用///

///

///

private void ServerSendData(stringstrMsg, IPEndPoint REP)

{byte[] byMsg =System.Text.Encoding.Default.GetBytes(strMsg.ToCharArray());

m_udpServer.Send(byMsg, byMsg.Length, REP);

}///

///发送本地节点信息///

///

///

public void SendLocalPoint(string strLocalIP, intiLocalPort, IPEndPoint REP)

{string strLocalPoint = "\x01\x02" + strLocalIP + ":" + iLocalPort.ToString() + "\x02\x01";

SendData(strLocalPoint, REP);

}///

///同时向指定的终端(包括公共终端和私有终端)打洞///

///

///

/// 打洞成功返回true,否则返回false

public voidStartBurrowTo(IPEndPoint pubEndPoint, IPEndPoint prEndPoint)

{

Thread burrowThread= new Thread(newThreadStart(BurrowProc));

m_toEndPoint.m_privateEndPoint=prEndPoint;

m_toEndPoint.m_publicEndPoint=pubEndPoint;

burrowThread.Start();

}///

///打洞线程///

private voidBurrowProc()

{

IPEndPoint prEndPoint=m_toEndPoint.m_privateEndPoint;

IPEndPoint pubEndPoint=m_toEndPoint.m_publicEndPoint;int j = 0;for (int i = 0; i < MAX_CONNECT_TRY; i++)

{

SendData("\x01\x07\x07\x01", prEndPoint);

SendData("\x01\x07\x07\x01", pubEndPoint);//等待接收线程标记修改

for (j = 0; j < MAX_CONNECT_TRY; j++)

{if(m_bRecvAck)

{

m_bRecvAck= false;

SendData("\x01\x07\x07\x01", prEndPoint);

Thread.Sleep(50);

SendData("\x01\x07\x07\x01", pubEndPoint);

UDPSockEventArgs args= new UDPSockEventArgs("");

args.RemoteEndPoint=pubEndPoint;if (OnNewConnectU != null)

{

OnNewConnectU(this, args);

}//Thread .Sleep (System .Threading.Timeout .Infinite );

return;

}else{

Thread.Sleep(100);

}

}//如果没有收到目标主机的回应,表明本次打//洞尝试失败,等待100毫秒后尝试下一次打洞

Thread.Sleep(100);

}//MAX_CONNECT_TRY 尝试都失败,表明打洞失败,抛出异常//throw new Exception(" 打洞失败!");

System.Windows.Forms.MessageBox.Show("打洞失败!");}///

///转发打洞请求消息,在服务器端使用///

///

///

///

public void SendBurrowRequest(string strSrcPrEndpoint, stringstrSrcPubEndPoint, IPEndPoint REP)

{string strBurrowMsg = "\x04\x07" + strSrcPrEndpoint + " " + strSrcPubEndPoint + "\x07\x04";

ServerSendData(strBurrowMsg, REP);

}///

///检查字符串中的命令///

private voidCheckCommand()

{intnPos;string strCmd =m_sbResponse.ToString();//如果接收远端用户名

if ((nPos = strCmd.IndexOf("\x01\x02")) > -1)

{

ReceiveName(strCmd, nPos);//反馈公共终给端远端主机

string strPubEPMsg = "\x03\x07" + m_remotePoint.ToString() + "\x07\x03";

SendData(strPubEPMsg, m_remotePoint);return;

}//如果接收我的公共终端

if ((nPos = strCmd.IndexOf("\x03\x07")) > -1)

{

ReceiveMyPublicEndPoint(strCmd, nPos);return;

}//如果是打洞请求消息

if ((nPos = strCmd.IndexOf("\x04\x07")) > -1)

{

ReceiveAndSendAck(strCmd, nPos);return;

}//如果是打洞回应消息

if ((nPos = strCmd.IndexOf("\x01\x07")) > -1)

{

m_bRecvAck= true;int nPos2 = strCmd.IndexOf("\x07\x01");if (nPos2 > -1)

{

m_sbResponse.Remove(nPos, nPos2- nPos + 2);

}return;

}//一般聊天消息

m_sbResponse.Remove(0, strCmd.Length);

RaiseMessageEvent(strCmd);

}///

///接收远端用户名///

///

///

private void ReceiveName(string strCmd, intnPos)

{int nPos2 = strCmd.IndexOf("\x02\x01");if (nPos2 == -1)

{return;

}

m_sbResponse.Remove(nPos, nPos2- nPos + 2);string strUserName = strCmd.Substring(nPos + 2, nPos2 - nPos - 2);

UDPSockEventArgs e= new UDPSockEventArgs("");

e.RemoteUserName=strUserName;

e.RemoteEndPoint=m_remotePoint;//触发用户登录事件

if (OnUserLogInU != null)

{

OnUserLogInU(this, e);

}

}///

///接收打洞请求的消息并发送回应///

///

///

private void ReceiveAndSendAck(string strCmd, intnPos)

{int nPos2 = strCmd.IndexOf("\x07\x04");if (nPos2 == -1)

{return;

}

m_sbResponse.Remove(nPos, nPos2- nPos + 2);string strBurrowMsg = strCmd.Substring(nPos + 2, nPos2 - nPos - 2);string[] strSrcPoint = strBurrowMsg.Split(' ');//分析控制字符串包含的节点信息

string[] strPrEndPoint = strSrcPoint[0].Split(':');string[] strPubEndPoint = strSrcPoint[1].Split(':');

m_requestPrivateEndPoint= new IPEndPoint(IPAddress.Parse(strPrEndPoint[0]), int.Parse(strPrEndPoint[1]));

m_requestPublicEndPoint= new IPEndPoint(IPAddress.Parse(strPubEndPoint[0]), int.Parse(strPubEndPoint[1]));//向请求打洞终端的方向打洞

StartBurrowTo(m_requestPublicEndPoint, m_requestPrivateEndPoint);

}///

///接收我的公共终端///

///

///

private void ReceiveMyPublicEndPoint(string strCmd, intnPos)

{int nPos2 = strCmd.IndexOf("\x07\x03");if (nPos2 == -1)

{return;

}

m_sbResponse.Remove(nPos, nPos2- nPos + 2);

m_strMyPublicEndPoint= strCmd.Substring(nPos + 2, nPos2 - nPos - 2);

}///

///触发一般UDP消息事件///

///

private void RaiseMessageEvent(stringstrMsg)

{

UDPSockEventArgs args= new UDPSockEventArgs("");

args.SockMessage=strMsg;

args.RemoteEndPoint=m_remotePoint;if (OnSockMessageU != null)

{

OnSockMessageU(this, args);

}

}///

///获取当前进程作为客户端的公共终端///

public stringMyPublicEndPoint

{get{returnm_strMyPublicEndPoint;

}

}///

///获取当前进程作为客户端的私有终端///

public stringMyPrivateEndPoint

{get{returnm_strMyPrivateEndPoint;

}

}

}///

///保存打洞消息要发向的节点信息///

classToEndPoint

{///

///私有节点///

publicIPEndPoint m_privateEndPoint;///

///公共节点///

publicIPEndPoint m_publicEndPoint;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值