C#實現UDP打洞
轉自:http://hi.baidu.com/sdfiyon/blog/item/63a6e039155e02f23a87ceb1.html
下面是UDP打洞程序包的源碼:
//WellKnown公用庫
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Net ;
using System.Net .Sockets ;
using System.Collections ;
namespace P2PWellKnown
{
/// <summary>
?????? /// UDP用戶登錄事件委托
/// </summary>
/// <param name="sender">事件源對象</param>
/// <param name="e">事件實體</param>
public delegate void UdpUserLogInDelegate(object sender,UDPSockEventArgs e);
?????? /// <summary>
?????? /// 一般UDP消息事件委托
?????? /// </summary>
?????? /// <param name="sender">事件源對象</param>
?????? /// <param name="e">事件實體</param>
?????? public delegate void UdpMessageDelegate(object sender,UDPSockEventArgs e);
?????? /// <summary>
?????? /// 初始化一個新連接的事件委托
?????? /// </summary>
?????? /// <param name="sender">事件源對象</param>
?????? /// <param name="e">事件實體</param>
?????? public delegate void UdpNewConnectDelegate(object sender,UDPSockEventArgs e);
/// <summary>
/// P2P共享數據類
/// </summary>
public class P2PConsts
{
???? /// <summary>
???? /// UDP服務器監聽端口
???? /// </summary>
???? public const int UDP_SRV_PORT???? = 2280;
???? /// <summary>
???? ///TCP服務器監聽端口
???? /// </summary>
???? public const int TCP_SRV_PORT =2000;
}
???
/// <summary>
/// FormatterHelper 序列化,反序列化消息的幫助類
/// </summary>
public class FormatterHelper
{
???? public static byte[] Serialize(object obj)
???? {
????? BinaryFormatter binaryF = new BinaryFormatter();
????? MemoryStream ms = new MemoryStream(1024*10);
????? binaryF.Serialize(ms, obj);
????? ms.Seek(0, SeekOrigin.Begin);
????? byte[] buffer = new byte[(int)ms.Length];
????? ms.Read(buffer, 0, buffer.Length);
????? ms.Close();
????? return buffer;
???? }
?
???? public static object Deserialize(byte[] buffer)
???? {
????? BinaryFormatter binaryF = new BinaryFormatter();
????? MemoryStream ms = new MemoryStream(buffer, 0, buffer.Length, false);
????? object obj = binaryF.Deserialize(ms);
????? ms.Close();
????? return obj;
???? }
}
?
/// <summary>
/// 用于承載UDPSock信息的事件類
/// </summary>
public class UDPSockEventArgs:EventArgs
{
???? /// <summary>
???? /// 要承載的消息
???? /// </summary>
???? private string m_strMsg;
???? /// <summary>
???? /// 用戶信息
???? /// </summary>
???? private string m_strUserName;
?????????? /// <summary>
?????????? /// 觸發該事件的公共終端
?????????? /// </summary>
?????????? private IPEndPoint m_EndPoint;
???? /// <summary>
???? /// 初始化UDPSock事件
???? /// </summary>
???? /// <param name="sMsg">用戶發送的信息</param>
???? public UDPSockEventArgs(string sMsg):base()
???? {
????? this.m_strMsg =sMsg;
???? }
???? /// <summary>
???? /// 遠端用戶名
???? /// </summary>
???? public string RemoteUserName
???? {
????? get
????? {
?????? return m_strUserName;
????? }
????? set
????? {
?????? m_strUserName=value;
????? }
???? }
?????????? /// <summary>
?????????? /// 一般套接字消息
?????????? /// </summary>
?????????? public string SockMessage
?????????? {
?????????????? get
?????????????? {
?????????????????? return m_strMsg;
?????????????? }
?????????????? set
?????????????? {
?????????????????? m_strMsg = value;
?????????????? }
?????????? }
?????????? /// <summary>
?????????? /// 公共遠端節點
?????????? /// </summary>
?????????? public IPEndPoint RemoteEndPoint
?????????? {
?????????????? get
?????????????? {
?????????????????? return m_EndPoint;
?????????????? }
?????????????? set
?????????????? {
?????????????????? m_EndPoint = value;
?????????????? }
?????????? }
}
}
?
//UDPP2PSock.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using P2PWellKnown;
namespace UDPP2P
{
?????? /// <summary>
?????? /// UDPP2P套接字管理類
?????? /// </summary>
?????? public class UDPP2PSock
?????? {
?????????? /// <summary>
?????????? /// 用戶登錄事件
?????????? /// </summary>
?????????? public event UdpUserLogInDelegate OnUserLogInU;
?????????? /// <summary>
?????????? /// 一般UDP消息事件
?????????? /// </summary>
?????????? public event UdpMessageDelegate OnSockMessageU;
?????????? /// <summary>
?????????? /// 初始化一個新連接事件
?????????? /// </summary>
?????????? public event UdpNewConnectDelegate OnNewConnectU;
?????????? /// <summary>
?????????? /// UDP服務器
?????????? /// </summary>
?????????? private UdpClient m_udpServer;
?????????? /// <summary>
?????????? /// UDP客戶端
?????????? /// </summary>
?????????? private UdpClient m_udpClient;
?????????? /// <summary>
?????????? /// 服務器實際上在本地機器上監聽的
?????????? /// 端口,用于當一臺計算機上同時啟
?????????? /// 動兩個可兩以上服務器進程時,標
?????????? /// 識不同的服務器進程
?????????? /// </summary>
?????????? private int m_iMyServerPort;
?????????? /// <summary>
?????????? /// 客戶端在本地機器上實際使用的端口,
?????????? /// 用于當一臺計算機上同時有兩個或兩
?????????? /// 個以上客戶端進程在運行時,標識不
?????????? /// 同的客戶端進程
?????????? /// </summary>
?????????? private int m_iMyClientPort;
?????????? /// <summary>
?????????? /// 標識是否已成功創服務器
?????????? /// </summary>
?????????? private bool m_bServerCreated;
?????????? /// <summary>
?????????? /// 標識是否已成功創建客戶端
?????????? /// </summary>
?????????? private bool m_bClientCreated;
?????????? /// <summary>
?????????? /// 服務器使用的線程
?????????? /// </summary>
?????????? private Thread m_serverThread;
?????????? /// <summary>
?????????? /// 客戶端使用的線程
?????????? /// </summary>
?????????? private Thread m_clientThread;
?????????? /// <summary>
?????????? /// 打洞線程
?????????? /// </summary>
?????????? //private Thread m_burrowThread;
?????????? /// <summary>
?????????? /// 遠端節點
?????????? /// </summary>
?????????? private IPEndPoint m_remotePoint;
?????????? /// <summary>
?????????? /// 當前進程作為客戶端的公共終端
?????????? /// </summary>
?????????? private string m_strMyPublicEndPoint;
?????????? /// <summary>
?????????? /// 當前進程作為客戶端的私有終端
?????????? /// </summary>
?????????? private string m_strMyPrivateEndPoint;
?????????? /// <summary>
?????????? /// 用于接受信息的StringBuilder實例
?????????? /// </summary>
?????????? private StringBuilder m_sbResponse = new StringBuilder();
?????????? /// <summary>
?????????? /// P2P打洞時標識是否收到回應消息
?????????? /// </summary>
?????????? private bool m_bRecvAck=false ;
?????????? /// <summary>
?????????? /// 請求向其方向打洞的私有終端
?????????? /// </summary>
?????????? private IPEndPoint m_requestPrivateEndPoint;
?????????? /// <summary>
?????????? /// 請求向其方向打洞的公共終端
?????????? /// </summary>
?????????? private IPEndPoint m_requestPublicEndPoint;
?????????? /// <summary>
?????????? /// 打洞消息要發向的節點
?????????? /// </summary>
?????????? private ToEndPoint m_toEndPoint;
?????????? /// <summary>
?????????? /// 用于標識是否已經和請求客戶端建立點對連接
?????????? /// </summary>
?????????? //private bool m_bHasConnected=false ;
?????????? /// <summary>
?????????? /// 創建服務器或客戶端的最大嘗試
?????????? /// 次數,為(65536-60000),防止
?????????? /// 因不能創建而限入死循環或使用
?????????? /// 無效端口
?????????? /// </summary>
?????????? private const int MAX_CREATE_TRY = 5536;
?????????? /// <summary>
?????????? /// 打洞時嘗試連接的最大嘗試次數
?????????? /// </summary>
?????????? private const int MAX_CONNECT_TRY = 10;
?????????? /// <summary>
?????????? /// 構造函數,初始化UDPP2P實例
?????????? /// </summary>
?????????? public UDPP2PSock()
?????????? {
?????????????? m_iMyServerPort = P2PConsts.UDP_SRV_PORT;
?????????????? m_iMyClientPort = 60000;
?????????????? m_bClientCreated = false;
?????????????? m_bServerCreated = false;
?????????????? m_toEndPoint = new ToEndPoint();
?????????????? m_serverThread = new Thread(new ThreadStart(RunUDPServer ));
?????????????? m_clientThread = new Thread(new ThreadStart(RunUDPClient ));
?????????????? //m_burrowThread = new Thread(new ThreadStart(BurrowProc));
?????????? }
?????????? /// <summary>
?????????? /// 創建UDP服務器
?????????? /// </summary>
?????????? public void CreateUDPSever()
?????????? {
?????????????? int iTryNum=0;
?????????????? //開始嘗試創建服務器
?????????????? while (!m_bServerCreated && iTryNum < MAX_CREATE_TRY)
?????????????? {
?????????????????? try
?????????????????? {
?????????????????????? m_udpServer = new UdpClient(m_iMyServerPort);
?????????????????????? m_bServerCreated = true;
?????????????????? }
?????????????????? catch
?????????????????? {
?????????????????????? m_iMyServerPort++;
?????????????????????? iTryNum++;
?????????????????? }
?????????????? }
?????????????? //創建失敗,拋出異常
?????????????? if (!m_bServerCreated && iTryNum == MAX_CREATE_TRY)
?????????????? {
?????????????????? throw new Exception ("創建服務器嘗試失敗!");
?????????????? }
?????????????? m_serverThread.Start();
????????????
?????????? }
?????????? /// <summary>
?????????? /// 創建UDP客戶端
?????????? /// </summary>
?????????? /// <param name="strServerIP">服務器IP</param>
?????????? /// <param name="iServerPort">服務器端口</param>
?????????? public void CreateUDPClient(string strServerIP,int iServerPort)
?????????? {
?????????????? int iTryNum = 0;
?????????????? //開始嘗試創建服務器
?????????????? while (!m_bClientCreated???? && iTryNum < MAX_CREATE_TRY)
?????????????? {
?????????????????? try
?????????????????? {
?????????????????????? m_udpClient???? = new UdpClient(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 = new IPEndPoint(IPAddress.Parse(strServerIP), iServerPort);
?????????????? string strLocalIP = (System.Net.Dns.GetHostAddresses("localhost"))[0].ToString();
?????????????? SendLocalPoint(strLocalIP, m_iMyClientPort, hostPoint);
?????????????? m_clientThread .Start();
?????????? }
?????????? /// <summary>
?????????? /// 運行UDP服務器
?????????? /// </summary>
?????????? private void RunUDPServer()
?????????? {
?????????????? while (true)
?????????????? {
?????????????????? byte[] msgBuffer =m_udpServer .Receive(ref m_remotePoint);
?????????????????? m_sbResponse.Append(System.Text.Encoding.Default.GetString(msgBuffer));
?????????????????? CheckCommand();
?????????????????? Thread.Sleep(10);
?????????????? }
?????????? }
?????????? /// <summary>
?????????? /// 運行UDP客戶端
?????????? /// </summary>
?????????? private void RunUDPClient()
?????????? {
?????????????? while (true)
?????????????? {
?????????????????? byte[] msgBuffer = m_udpClient.Receive(ref m_remotePoint);
?????????????????? m_sbResponse.Append(System.Text.Encoding.Default.GetString(msgBuffer));
?????????????????? CheckCommand();
?????????????????? Thread.Sleep(10);
?????????????? }
?????????? }
?????????? /// <summary>
?????????? /// 銷毀UDP服務器
?????????? /// </summary>
?????????? public void DisposeUDPServer()
?????????? {
?????????????? m_serverThread.Abort();
?????????????? m_udpServer.Close();
?????????? }
?????????? /// <summary>
?????????? /// 銷毀UDP客房端
?????????? /// </summary>
?????????? public void DisposeUDPClient()
?????????? {
?????????????? m_clientThread.Abort();
?????????????? m_udpClient.Close();
?????????? }
?????????? /// <summary>
?????????? /// 發送消息
?????????? /// </summary>
?????????? /// <param name="strMsg">消息內容</param>
?????????? /// <param name="REP">接收節點</param>
?????????? public void SendData(string strMsg,IPEndPoint REP)
?????????? {
?????????????? byte[] byMsg = System.Text.Encoding.Default.GetBytes(strMsg.ToCharArray());
?????????????? m_udpClient.Send(byMsg, byMsg.Length, REP);
?????????? }
?????????? /// <summary>
?????????? /// 發送消息,服務器專用
?????????? /// </summary>
?????????? /// <param name="strMsg">消息內容</param>
?????????? /// <param name="REP">接收節點</param>
?????????? private void ServerSendData(string strMsg,IPEndPoint REP)
?????????? {
?????????????? byte[] byMsg = System.Text.Encoding.Default.GetBytes(strMsg.ToCharArray());
?????????????? m_udpServer.Send(byMsg, byMsg.Length, REP);
?????????? }
?????????? /// <summary>
?????????? /// 發送本地節點信息
?????????? /// </summary>
?????????? /// <param name="strLocalIP">本地IP</param>
?????????? /// <param name="iLocalPort">本地端口</param>
?????????? public void SendLocalPoint(string strLocalIP, int iLocalPort,IPEndPoint REP)
?????????? {
?????????????? string strLocalPoint = "/x01/x02" + strLocalIP + ":" + iLocalPort.ToString() + "/x02/x01";
?????????????? SendData(strLocalPoint, REP);
?????????? }
/// <summary>
????????? /// 同時向指定的終端(包括公共終端和私有終端)打洞
????????? /// </summary>
????????? /// <param name="pubEndPoint">公共終端</param>
????????? /// <param name="prEndPoint">私有終端</param>
????????? /// <returns>打洞成功返回true,否則返回false</returns>
????????? public void StartBurrowTo(IPEndPoint pubEndPoint, IPEndPoint prEndPoint)
????????? {
????????????? Thread burrowThread = new Thread(new ThreadStart(BurrowProc));
????????????? m_toEndPoint.m_privateEndPoint = prEndPoint;
????????????? m_toEndPoint.m_publicEndPoint = pubEndPoint;
????????????? burrowThread.Start();
????????? }
????????
????????? /// <summary>
????????? /// 打洞線程
????????? /// </summary>
????????? private void BurrowProc()
????????? {
????????????? 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("打洞失敗!");
????????? }
?????????
????????? /// <summary>
????????? /// 轉發打洞請求消息,在服務器端使用
????????? /// </summary>
????????? /// <param name="strSrcPrEndpoint">請求轉發的源私有終端</param>
????????? /// <param name="strSrcPubEndPoint">請求轉發的源公共終端</param>
????????? /// <param name="REP">轉發消息到達的目的終端</param>
????????? public void SendBurrowRequest(string strSrcPrEndpoint, string strSrcPubEndPoint,IPEndPoint REP)
????????? {
????????????? string strBurrowMsg = "/x04/x07" + strSrcPrEndpoint + " " + strSrcPubEndPoint + "/x07/x04";
????????????? ServerSendData(strBurrowMsg, REP);
????????? }
????????? /// <summary>
????????? /// 檢查字符串中的命令
????????? /// </summary>
????????? private void CheckCommand()
????????? {
????????????? int nPos;
????????????? 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);
????????????????? }
????????????????? /*
????????????????? if (m_requestPublicEndPoint != null)
????????????????? {
????????????????????? if (!m_bHasConnected)
????????????????????? {
????????????????????????? m_bHasConnected = true;
????????????????????????? UDPSockEventArgs args = new UDPSockEventArgs("");
????????????????????????? args.RemoteEndPoint = m_requestPublicEndPoint;
????????????????????????? if (OnNewConnectU != null)
????????????????????????? {
????????????????????????????? OnNewConnectU(this, args);
????????????????????????? }
????????????????????????? m_requestPublicEndPoint = null;
????????????????????? }
????????????????? }*/
????????????????? return;
????????????? }
????????????? //一般聊天消息
????????????? m_sbResponse.Remove(0, strCmd.Length);
????????????? RaiseMessageEvent(strCmd);
????????? }
????????? /// <summary>
????????? /// 接收遠端用戶名
????????? /// </summary>
????????? /// <param name="strCmd">包含用戶名的控制信息</param>
????????? /// <param name="nPos"></param>
????????? private void ReceiveName(string strCmd, int nPos)
????????? {
????????????? 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);
????????????? }
????????? }
????????? /// <summary>
????????? /// 接收打洞請求的消息并發送回應
????????? /// </summary>
????????? /// <param name="strCmd"></param>
????????? /// <param name="nPos"></param>
????????? private void ReceiveAndSendAck(string strCmd, int nPos)
????????? {
????????????? 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);
????????? }
????????? /// <summary>
????????? /// 接收我的公共終端
????????? /// </summary>
????????? /// <param name="strCmd">包含公共終端的控制信息</param>
????????? /// <param name="nPos">控制字符串的起始位置</param>
????????? private void ReceiveMyPublicEndPoint(string strCmd, int nPos)
????????? {
????????????? 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);
????????? }
????????? /// <summary>
????????? /// 觸發一般UDP消息事件
????????? /// </summary>
????????? /// <param name="strMsg">消息內容</param>
????????? private void RaiseMessageEvent(string strMsg)
????????? {
????????????? UDPSockEventArgs args = new UDPSockEventArgs("");
????????????? args.SockMessage = strMsg;
????????????? args.RemoteEndPoint = m_remotePoint;
????????????? if (OnSockMessageU != null)
????????????? {
????????????????? OnSockMessageU(this, args);
????????????? }
????????? }
????????? /// <summary>
????????? /// 獲取當前進程作為客戶端的公共終端
????????? /// </summary>
????????? public string MyPublicEndPoint
????????? {
????????????? get
????????????? {
????????????????? return m_strMyPublicEndPoint;
????????????? }
????????? }
????????? /// <summary>
????????? /// 獲取當前進程作為客戶端的私有終端
????????? /// </summary>
????????? public string MyPrivateEndPoint
????????? {
????????????? get
????????????? {
????????????????? return m_strMyPrivateEndPoint;
????????????? }
????????? }
????? }
????
????? /// <summary>
????? /// 保存打洞消息要發向的節點信息
????? /// </summary>
????? class ToEndPoint
????? {
????????? /// <summary>
????????? /// 私有節點
????????? /// </summary>
????????? public IPEndPoint m_privateEndPoint;
????????? /// <summary>
????????? /// 公共節點
????????? /// </summary>
????????? public IPEndPoint m_publicEndPoint;
????? }
}
?????????? 關于如何使用上述程序包的一些說明:
?????????? 主要程序的初始化,參考代碼如下:
????????????? //創建UDP服務器和客戶端
????????????? try
????????????? {
????????????????? string strServerIP="127.0.0.1"
????????????????? udpSock = new UDPP2PSock();
????????????????? udpSock.OnUserLogInU += new UdpUserLogInDelegate(OnUserLogInU);
????????????????? udpSock.OnNewConnectU += new UdpNewConnectDelegate(OnNewConnectU);
????????????????? udpSock.CreateUDPSever();
????????????????? udpSock.CreateUDPClient(strServerIP, P2PConsts.UDP_SRV_PORT);
????????????? }
????????????? catch (Exception ex)
????????????? {
????????????? }