您的位置:首页 > 编程语言 > C#

C#实现UDP打洞 原理及代码(二)

2008-10-31 19:54 393 查看
//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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: