C#实现UDP打洞.docx
《C#实现UDP打洞.docx》由会员分享,可在线阅读,更多相关《C#实现UDP打洞.docx(16页珍藏版)》请在冰豆网上搜索。
C#实现UDP打洞
C#实现UDP打洞
虽然打洞技术的实现源码在网上也可以找到,但用C#实现的源码并不多见。
另外下面的代码为了达到功能与界面的分离,采用了事件进行消息通信,程序具有一定的可移植性和可扩展性,也最能体现我的C#编码风格。
不过代码没有严格遵循模式设计的原则,希望网友们如果有更优化的代码能提出来共享一下。
总体上来说,下面的程序包还有它存在的使用价值和意义,所以发表出来共享一下。
下面是UDP打洞程序包的源码:
//WellKnown公用库
usingSystem;
usingSystem.IO;
usingSystem.Runtime.Serialization.Formatters.Binary;
usingSystem.Net;
usingSystem.Net.Sockets;
usingSystem.Collections;
namespaceP2PWellKnown
{
///
///UDP用户登录事件委托
///
///事件源对象
///事件实体
publicdelegatevoidUdpUserLogInDelegate(objectsender,UDPSockEventArgse);
///
///一般UDP消息事件委托
///
///事件源对象
///事件实体
publicdelegatevoidUdpMessageDelegate(objectsender,UDPSockEventArgse);
///
///初始化一个新连接的事件委托
///
///事件源对象
///事件实体
publicdelegatevoidUdpNewConnectDelegate(objectsender,UDPSockEventArgse);
///
///P2P共享数据类
///
publicclassP2PConsts
{
///
///UDP服务器监听端口
///
publicconstintUDP_SRV_PORT =2280;
///
///TCP服务器监听端口
///
publicconstintTCP_SRV_PORT=2000;
}
///
///FormatterHelper序列化,反序列化消息的帮助类
///
publicclassFormatterHelper
{
publicstaticbyte[]Serialize(objectobj)
{
BinaryFormatterbinaryF=newBinaryFormatter();
MemoryStreamms=newMemoryStream(1024*10);
binaryF.Serialize(ms,obj);
ms.Seek(0,SeekOrigin.Begin);
byte[]buffer=newbyte[(int)ms.Length];
ms.Read(buffer,0,buffer.Length);
ms.Close();
returnbuffer;
}
publicstaticobjectDeserialize(byte[]buffer)
{
BinaryFormatterbinaryF=newBinaryFormatter();
MemoryStreamms=newMemoryStream(buffer,0,buffer.Length,false);
objectobj=binaryF.Deserialize(ms);
ms.Close();
returnobj;
}
}
///
///用于承载UDPSock信息的事件类
///
publicclassUDPSockEventArgs:
EventArgs
{
///
///要承载的消息
///
privatestringm_strMsg;
///
///用户信息
///
privatestringm_strUserName;
///
///触发该事件的公共终端
///
privateIPEndPointm_EndPoint;
///
///初始化UDPSock事件
///
///用户发送的信息
publicUDPSockEventArgs(stringsMsg):
base()
{
this.m_strMsg=sMsg;
}
///
///远端用户名
///
publicstringRemoteUserName
{
get
{
returnm_strUserName;
}
set
{
m_strUserName=value;
}
}
///
///一般套接字消息
///
publicstringSockMessage
{
get
{
returnm_strMsg;
}
set
{
m_strMsg=value;
}
}
///
///公共远端节点
///
publicIPEndPointRemoteEndPoint
{
get
{
returnm_EndPoint;
}
set
{
m_EndPoint=value;
}
}
}
}
//UDPP2PSock.cs
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Net;
usingSystem.Net.Sockets;
usingSystem.Threading;
usingP2PWellKnown;
namespaceUDPP2P
{
///
///UDPP2P套接字管理类
///
publicclassUDPP2PSock
{
///
///用户登录事件
///
publiceventUdpUserLogInDelegateOnUserLogInU;
///
///一般UDP消息事件
///
publiceventUdpMessageDelegateOnSockMessageU;
///
///初始化一个新连接事件
///
publiceventUdpNewConnectDelegateOnNewConnectU;
///
///UDP服务器
///
privateUdpClientm_udpServer;
///
///UDP客户端
///
privateUdpClientm_udpClient;
///
///服务器实际上在本地机器上监听的
///端口,用于当一台计算机上同时启
///动两个可两以上服务器进程时,标
///识不同的服务器进程
///
privateintm_iMyServerPort;
///
///客户端在本地机器上实际使用的端口,
///用于当一台计算机上同时有两个或两
///个以上客户端进程在运行时,标识不
///同的客户端进程
///
privateintm_iMyClientPort;
///
///标识是否已成功创服务器
///
privateboolm_bServerCreated;
///
///标识是否已成功创建客户端
///
privateboolm_bClientCreated;
///
///服务器使用的线程
///
privateThreadm_serverThread;
///
///客户端使用的线程
///
privateThreadm_clientThread;
///
///打洞线程
///
//privateThreadm_burrowThread;
///
///远端节点
///
privateIPEndPointm_remotePoint;
///
///当前进程作为客户端的公共终端
///
privatestringm_strMyPublicEndPoint;
///
///当前进程作为客户端的私有终端
///
privatestringm_strMyPrivateEndPoint;
///
///用于接受信息的StringBuilder实例
///
privateStringBuilderm_sbResponse=newStringBuilder();
///
///P2P打洞时标识是否收到回应消息
///
privateboolm_bRecvAck=false;
///
///请求向其方向打洞的私有终端
///
privateIPEndPointm_requestPrivateEndPoint;
///
///请求向其方向打洞的公共终端
///
privateIPEndPointm_requestPublicEndPoint;
///
///打洞消息要发向的节点
///
privateToEndPointm_toEndPoint;
///
///用于标识是否已经和请求客户端建立点对连接
///
//privateboolm_bHasConnected=false;
///
///创建服务器或客户端的最大尝试
///次数,为(65536-60000),防止
///因不能创建而限入死循环或使用
///无效端口
///
privateconstintMAX_CREATE_TRY=5536;
///
///打洞时尝试连接的最大尝试次数
///
privateconstintMAX_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=newThread(newThreadStart(RunUDPServer));
m_clientThread=newThread(newThreadStart(RunUDPClient));
//m_burrowThread=newThread(newThreadStart(BurrowProc));
}
///
///创建UDP服务器
///
publicvoidCreateUDPSever()
{
intiTryNum=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)
{
thrownewException("创建服务器尝试失败!
");
}
m_serverThread.Start();
}
///
///创建UDP客户端
///
///服务器IP
///服务器端口
publicvoidCreateUDPClient(stringstrServerIP,intiServerPort)
{
intiTryNum=0;
//开始尝试创建服务器
while(!
m_bClientCreated &&iTryNum {
try
{
m_udpClient =newUdpClient(m_iMyClientPort);
m_bClientCreated =true;
stringstrIPAddress=(System.Net.Dns.GetHostAddresses("localhost")[0]).ToString();
m_strMyPrivateEndPoint=strIPAddress+":
"+m_iMyClientPort.ToString();
}
catch
{
m_iMyClientPort++;
iTryNum++;
}
}
//创建失败,抛出异常
if(!
m_bClientCreated &&iTryNum==MAX_CREATE_TRY)
{
thrownewException("创建客户端尝试失败!
");
}
IPEndPointhostPoint=newIPEndPoint(IPAddress.Parse(strServerIP),iServerPort);
stringstrLocalIP=(System.Net.Dns.GetHostAddresses("localhost"))[0].ToString();
SendLocalPoint(strLocalIP,m_iMyClientPort,hostPoint);
m_clientThread.Start();
}
///
///运行UDP服务器
///
privatevoidRunUDPServer()
{
while(true)
{
byte[]msgBuffer=m_udpServer.Receive(refm_remotePoint);
m_sbResponse.Append(System.Text.Encoding.Default.GetString(msgBuffer));
CheckCommand();
Thread.Sleep(10);
}
}
///
///运行UDP客户端
///
privatevoidRunUDPClient()