之前一直在犹豫该不该发表这篇文章。从网上看到的很多技术牛人,觉得自己所掌握的技术是如此渺小。我并不适合于走技术这条路,为了寻求一个更完美的人生,早已决定了不继续走技术这条路线,所以也不太愿意发表一些技术性的文章。
最近一段时间的思索,发现在自己的一直所追求的是思想与智慧的美。曾经在技术上进行了两年左右的探索,但从自己对世界思索的收获远比学习技术给自己带来的收获要多得多,尽管自己对周围世界的理解有点空头思想的之嫌,但既是自己追求,我想就应该坚持走下去,人生也就这么一回。
最后决定发表这篇文章的直接原因是毕竟自己曾经在技术路上走过,发表点技术性的文章给点象征性的表示;其次的原因是在IPv6版本在世界范围内普遍使用,IPv4淡出网络市场之前,打洞技术在很长一段时间内还有它不可替代的意义和地位;第三是我欣赏打洞原理的思想,想想当初网络提出NAT技术的时候,如果没有留下这个可以打洞的后门,恐怕“打洞”这个名词将不会在IT历史上留名,现在风行的即时通信工具技术的难度也将难以想象。有点遗憾的是一直没有去追查当初这个后门是有意还是无意留下的,不过我宁愿相信是有意留下的,因为这体现了一种高瞻远瞩的眼光,留下这个后门为今天网络的繁荣作了长远的铺垫。至于打洞原理在网上搜一下多的是,这里就没有必要再赘述。
虽然打洞技术的实现源码在网上也可以找到,但用C#实现的源码并不多见。另外下面的代码为了达到功能与界面的分离,采用了事件进行消息通信,程序具有一定的可移植性和可扩展性,也最能体现我的C#编码风格。不过代码没有严格遵循模式设计的原则,希望网友们如果有更优化的代码能提出来共享一下。总体上来说,下面的程序包还有它存在的使用价值和意义,所以发表出来共享一下。
下面是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;
us