网上有很多关于p2p打洞的文章,但都只说了原理或者很简单的编程过程,但因为UDP传输有严重丢包问题,另外也不可能一共就两台电脑需要p2p连接,所以必须要有个详细规划,否则很可能连不通或者创建连接时浪费时间
p2p打洞原理就不说,可以看这个 http://blog.programfan.com/article.asp?id=18828
这里说说具体编程:
(我是第一次写网络软件,写这个见笑了哈,图也画的不好)[em12]

S为服务器,A,B分别为不同nat后的电脑(这里不讨论公网或同nat下client)
因为要考虑很多个客服端连接问题,这里用了2个winsock,W1为主sock,用于和server保持连接,W2用于p2p连接。因为要考虑server负荷量,这里全用UDP协议。因为A,B电脑上的client都是一样的程序,所以我们设置不同的状态,这里用数字标记,否则会出现混乱。
具体步骤(比普通文章写的复杂些,就因为要考虑以上几个问题):

0.A,B等client都用w1向server连接后,serve创建一个IP地址表记住所有w1的IP和port,回传标记后,client记住连接标记=0
1.现在a发起请求,需要和b点对点传输,用timer控制a.w2向s持续发出请求(比如间隔2秒,避免丢包出现连接不成功)标记状态=1
2.s收到请求信息,同时得到a.W2的地址(IP一样,但port不同),然后查找b.w1的地址,向b.w1发请求信息,同时将a的地址传给b,如果收到,记下地址,标记状态=2
3.由timer控制b.w2持续发送消息到s,告知对方已经收到IP,s收到消息后同时得到b.w2IP 和port,转发到a.w1,状态3
4.w1收到该消息,更改w2的remotehost和remoteport到b.W2,任然由timer控制持续发送消息,同时由timer控制a.w1持续向s发送消息(已经收到IP),状态4
5。s帮助转发消息到b.W1,b.w1收到后更改b.w2的remotehost和remoteport到a.w2,任然有timer控制持续发消息。a.w2收到消息(现在是来自b的),表明已连接,a.w1停止发送到s的消息,状态5。b.w2收到消息,更改状态为5.将timer.interval加大,作为心跳包定时器。
连接完成。

现在把以上过程整合到一个程序中:
每一条消息都做不同的标记,由timer一直控制w2(只是按需要更改间隔时间),w收到不同消息后做以上操作,程序就完工了。