关于采用UDP协议进行打洞以进行P2P会话的原理,我本来想写一篇文章作说明,但是现在已经有一篇文章把原理性的东西解释清楚了,我在这里不再作这部分的重复,可以参见这里:
P2P 之 UDP穿透NAT的原理与实现(附源代码)--
下面解释一下上面的文章中没有提及或者说我觉得比较欠缺的地方.
私有地址/端口和公有地址/端口:我们知道,现在大部分网络采用的都是NAPT(Network Address/Port Translator)了,这个东东的作用是一个对外的对话在经过NAT之后IP地址和端口号都会被改写,在这里把一次会话中客户自己认为在使用的IP地址和端口号成为私有地址/端口,而把经过NAPT之后被改写的IP地址和端口号称为公有地址/端口.或者可以这么理解,私有地址/端口是你家里人对你的昵称而公有地址/端口则是你真正对外公开的名字.如何获得用户的私用地址/端口号,这个很简单了,而要得到公有地址/端口号就要在连接上另一台机器之后由那台机器看到的IP地址和端口号来表示.
如果明白了上面的东西,下面进入我们的代码,在这里解释一下关键部分的实现:
客户端首先得到自己的私有地址/终端,然后向server端发送登陆请求,server端在得到这个请求之后就可以知道这个client端的公有地址/终端,server会为每一个登陆的client保存它们的私有地址/端口和公有地址/端口.
OK,下面开始关键的打洞流程.假设client A要向client B对话,但是A不知道B的地址,即使知道根据NAT的原理这个对话在第一次会被拒绝,因为client B的NAT认为这是一个从没有过的外部发来的请求.这个时候,A如果发现自己没有保存B的地址,或者说发送给B的会话请求失败了,它会要求server端让B向A打一个洞,这个B-&A的会话意义在于它使NAT
B认为A的地址/端口是可以通过的地址/端口,这样A再向B发送对话的时候就不会再被NAT B拒绝了.打一个比方来说明打洞的过程,A想来B家做客,但是遭到了B的管家NAT B的拒绝,理由是:我从来没有听我家B提过你的名字,这时A找到了A,B都认识的朋友server,要求server给B报一个信,让B去跟管家说A是我的朋友,于是,B跟管家NAT B说,A是我认识的朋友,这样A的访问请求就不会再被管家NAT B所拒绝了.简而言之,UDP打洞就是一个通过server保存下来的地址使得彼此之间能够直接通信的过程,server只管帮助建立连接,在建立间接之后就不再介入了.
好了,原理性的东西解释到这里,附件中有一个完整的P2P演示程序,命令行模式下,包括server端和client端,在运行的时候首先启动server端,然后打开几个client端分别登陆,之后彼此之间就可以相互通信了.程序在本机上测试通过,也就是测试的环境server和client都是一台机器,还没有在不同的机器上测试过,不知道会不会有问题:)
1)P2P 之 UDP穿透NAT的原理与实现(附源代码)-paf.net/Class/hack/3804825.htm
2)王艳平&&Windows网络与通信程序设计&& &
建立穿越NAT设备的p2p的TCP连接只比UDP复杂一点点,TCP协议的&打洞&从协议层来看是与UDP的&打洞&过程非常相似的。尽管如此,基于TCP协议的打洞至今为止还没有被很好的理解,这也造成了对其提供支持的NAT设备不是很多。在NAT设备支持的前提下,基于TCP的&打洞&技术实际上与基于UDP的&打洞&技术一样快捷、可靠。实际上,只要NAT设备支持的话,基于TCP的p2p技术的健壮性将比基于UDP的技术的更强一些,因为TCP协议的状态机给出了一种标准的方法来精确的获取某个TCP
session的生命期,而UDP协议则无法做到这一点。
一. 套接字和TCP端口的重用
实现基于TCP协议的p2p&打洞&过程中,最主要的问题不是来自于TCP协议,而是来自于来自于应用程序的API接口。这是由于标准的伯克利(Berkeley)套接字的API是围绕着构建客户端/服务器程序而设计的,API允许TCP流套接字通过调用connect()函数来建立向外的连接,或者通过listen()和accept函数接受来自外部的连接,但是,API不提供类似UDP那样的,同一个端口既可以向外连接,又能够接受来自外部的连接。而且更糟的是,TCP的套接字通常仅允许建立1对1的响应,即应用程序在将一个套接字绑定到本地的一个端口以后,任何试图将第二个套接字绑定到该端口的操作都会失败。
为了让TCP&打洞&能够顺利工作,我们需要使用一个本地的TCP端口来监听来自外部的TCP连接,同时建立多个向外的TCP连接。幸运的是,所有的主流操作系统都能够支持特殊的TCP套接字参数,通常叫做&SO_REUSEADDR&,该参数允许应用程序将多个套接字绑定到本地的一个endpoint(只要所有要绑定的套接字都设置了SO_REUSEADDR参数即可)。BSD系统引入了SO_REUSEPORT参数,该参数用于区分端口重用还是地址重用,在这样的系统里面,上述所有的参数必须都设置才行。
二. 打开p2p的TCP流
假定客户端A希望建立与B的TCP连接。我们像通常一样假定A和B已经与公网上的已知服务器S建立了TCP连接。服务器记录下来每个联入的客户端的公网和内网的endpoints,如同为UDP服务的时候一样。从协议层来看,TCP&打洞&与UDP&打洞&是几乎完全相同的过程。
1、客户端A使用其与服务器S的连接向服务器发送请求,要求服务器S协助其连接客户端B。
2、S将B的公网和内网的TCP endpoint返回给A,同时,S将A的公网和内网的endpoint发送给B。
3、客户端A和B使用连接S的端口异步地发起向对方的公网、内网endpoint的TCP连接,同时监听各自的本地TCP端口是否有外部的连接联入。
4、A和B开始等待向外的连接是否成功,检查是否有新连接联入。如果向外的连接由于某种网络错误而失败,如:&连接被重置&或者&节点无法访问&,客户端只需要延迟一小段时间(例如延迟一秒钟),然后重新发起连接即可,延迟的时间和重复连接的次数可以由应用程序编写者来确定。
5、TCP连接建立起来以后,客户端之间应该开始鉴权操作,确保目前联入的连接就是所希望的连接。如果鉴权失败,客户端将关闭连接,并且继续等待新的连接联入。客户端通常采用&先入为主&的策略,只接受第一个通过鉴权操作的客户端,然后将进入p2p通信过程不再继续等待是否有新的连接联入。
与UDP不同的是,使用UDP协议的每个客户端只需要一个套接字即可完成与服务器S通信,并同时与多个p2p客户端通信的任务,而TCP客户端必须处理多个套接字绑定到同一个本地TCP端口的问题,如图所示。
现在来看更加实际的一种情景,A与B分别位于不同的NAT设备后面,并且假定端口号是TCP协议的端口号,而不是UDP的端口号。客户端向彼此公网endpoint发起连接的操作,会使得各自的NAT设备打开新的&洞&允许A与B的TCP数据通过。如果NAT设备支持TCP&打洞&操作的话,一个在客户端之间的基于TCP协议的流通道就会自动建立起来。如果A向B发送的第一个SYN包发到了B的NAT设备,而B在此前没有向A发送SYN包,B的NAT设备会丢弃这个包,这会引起A的&连接失败&或&无法连接&问题。而此时,由于A已经向B发送过SYN包,B发往A的SYN包将被看作是由A发往B的包的回应的一部分,所以B发往A的SYN包会顺利地通过A的NAT设备,到达A,从而建立起A与B的p2p连接。
三. 从应用程序的角度来看TCP&打洞&
从应用程序的角度来看,在进行TCP&打洞&的时候都发生了什么呢?假定A首先向B发出SYN包,该包发往B的公网endpoint,并且被B的NAT设备丢弃,但是B发往A的公网endpoint的SYN包则通过A的NAT到达了A,然后,会发生以下的两种结果中的一种,具体是哪一种取决于操作系统对TCP协议的实现:
(1)A的TCP事先会发现收到的SYN包就是其发起连接并希望联入的B的SYN包,通俗一点来说就是&说曹操,曹操到&的意思,本来A要去找B,结果B自己找上门来了。A的TCP协议栈因此会把B做为A向B发起连接connect的一部分,并认为连接已经成功。程序A调用的异步connect()函数将成功返回,A的listen()等待从外部联入的函数将没有任何反映。此时,B联入A的操作在A程序的内部被理解为A联入B连接成功,并且A开始使用这个连接与B开始p2p通信。
由于收到的SYN包中不包含A需要的ACK数据,因此,A的TCP将用SYN-ACK包回应B的公网endpoint,并且将使用先前A发向B的SYN包一样的序列号。一旦B的TCP收到由A发来的SYN-ACK包,则把自己的ACK包发给A,然后两端建立起TCP连接。简单的说,第一种,就是即使A发往B的SYN包被B的NAT丢弃了,但是由于B发往A的包到达了A。结果是,A认为自己连接成功了,B也认为自己连接成功了,不管是谁成功了,总之连接是已经建立起来了。
(2)另外一种结果是,A的TCP实现没有像(1)中所讲的那么&智能&,它没有发现现在联入的B就是自己希望联入的。就好比在机场接人,明明遇到了自己想要接的人却不认识,误认为是其它的人,安排别人给接走了,后来才知道是自己错过了机会,但是无论如何,人已经接到了任务已经完成了。然后,A通过常规的listen()函数和accept()函数得到与B的连接,而由A发起的向B的公网endpoint的连接会以失败告终。尽管A向B的连接失败,A仍然得到了B发起的向A的连接,等效于A与B之间已经联通,不管中间过程如何,A与B已经连接起来了,结果是A和B的基于TCP协议的p2p连接已经建立起来了。
第一种结果适用于基于BSD的操作系统对于TCP的实现,而第二种结果更加普遍一些,多数linux和windows系统都会按照第二种结果来处理。
下面就是非转载部分了,我看后的感想:(如没有特殊声明,一律是在windows环境下)
这个所谓的&洞&就是SOCKET,套接字.
端口复用就是在一个SOCKET上既可以listen()也可以connect().
有一点需要说明,在我看来所谓的端口有两种形式,一种是主动连接的,一种是被动连接的.也就是说当我去连接某服务器的某端口的时候,我自身也会开启一个端口,这样才能进行通讯.我们一般知道的都是被动连接的端口,而主动连接的端口是由系统随机分配的.不信的话你可以打开一个网页,然后开启CMD窗口输入&netstat -an&,你会发现有一个或者几个信息,意思就是本地的XXX端口连接到远程的80端口(Web服务),我说的也就是这个意思了.但,实际情况却更复杂,本地开的端口在外部的访问不到的,因为从本地端口发送的数据要经过路由,而路由经过分析包后知道是建立连接,所以路由又开了一个端口用于接收外部的包,那么自己的端口(内网端口)和路由开的端口(外网端口)会形成一个映射,是这个样子.
&打洞&,就是说:
两个电脑A和B与服务器S,A和B都与S建立连接,此时有两个SOCKET,A和S算一个(叫做S_AS),B和S算一个(叫做S_BS),这两个都设置了端口复用
A和B分别创建新的SOCKET(设置端口复用)并调用listen(),就是A创建新的SOCKET绑定到S_AS的端口上监听(内网端口),B也一样
A和B通过服务器分别拿到对方的外网IP和端口号(服务器获取,主动连接的,路由开的端口)
告诉服务器我们(A和B)都准备好了,这时服务器发出指令,准备P2P.
此时A和B分别去连接对方,就是,A去连接S_BS的外网端口,B去连接S_AS的外网端口,至少有一方可以连接到另一方,连接建立.
(监听自己的内网端口,连接对方的外网端口)
至于为什么能连接上,请看上面文章中我标注红色字体的描述.
做过网络编程的人都应该知道,TCP之所以可靠是因为在建立连接的时候要经过&三次握手&(当然还有其他因素),要事先打好招呼,这三个数据包分别叫做SYN/ACK/RST(说错了别怪我),由于A和B都是处在内网,彼此相隔两个路由器(自己这边一个,对方那边一个),建立连接的时候自己发送的SYN包能通过自己的路由,却不能通过对方的路由,所以包被丢弃,而此时对方也发送一个SYN包过来,因为自己已经发送了SYN包,所以自己这边的路由会认为对方发来的SYN包是回应我的SYN包,所以不会丢弃包,继续传递给自己,而自己也会把对方发来的包当做回应自己的包,所以做处理(当然不是正常的三次握手,SYN和SYN),还会发送ACK给对方,然后对方给我RST包,再然后,连接建立......
想来想去怎么都是觉得是在忽悠路由器,忽悠忽悠就建立连接了.
最后的结果只有一种:
A连接上了S_BS的端口,或者,B连接上了S_AS的端口,总之A和B通了.
据资料所知貌似没有都连接上的情况.
查阅资料就学到这些,也不知道对不对,有空敲代码试试看~~~
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:96749次
积分:1375
积分:1375
排名:第14278名
原创:18篇
转载:161篇
评论:14条
(1)(6)(2)(5)(11)(3)(2)(14)(11)(26)(6)(5)(4)(10)(7)(4)(11)(13)(10)(2)(5)(3)(5)(5)(4)(1)(1)(2)
http://blog.csdn.net/sailor_8318/article/category/323453 http://blog.csdn.net/z2007b http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/docs/kernelAPI/index.html http://blog.csdn.net/droidphone/article/details/7467436 http://blog.csdn.net/tigerjb/article/details/6069516
/android/archive//android-ubuntu-linux-kernel.html 华清主页http://www.embedu.org/Column/index12.htm 一个关于驱动挺好的博客http://blog.chinaunix.net/uid//cid-29897-list-1.html查看: 4207|回复: 6
注册时间最后登录在线时间43 小时威望355 UID384425阅读权限40精华0主题积分355帖子金币37
三星若人, 积分 355, 距离下一级还需 45 积分
积分355帖子金币37
我的p2p网络连接有时能连上& & 连上了又搜索不到& &搜索到了资源全都是*& &怎么弄得啊
附件: 您需要
才可以下载或查看,没有帐号?
网络温不稳定和迅雷下载速度没多大关系(个人认为)温不稳定看这两个电脑,一直亮着说明稳定急了,闪来闪去说明不太稳定,想图里这样全暗,那...不用说明了
注册时间最后登录在线时间706 小时威望21250 UID435100阅读权限120精华0主题积分21250帖子金币1891
七宗罪:饕餮、贪婪、纵欲、懒惰、嫉妒、骄傲、愤怒
一冠若人, 积分 21250, 距离下一级还需 18750 积分
积分21250帖子金币1891
<font color="#5907847 发表于
好吧、我家网络很好的& &从来不卡& &迅雷下载普通会员都在200KB/s以上啊
网络温不稳定和迅雷下载速度没多大关系(个人认为)温不稳定看这两个电脑,一直亮着说明稳定急了,闪来闪去说明不太稳定,想图里这样全暗,那...不用说明了
本帖子中包含更多资源
才可以下载或查看,没有帐号?
注册时间最后登录在线时间567 小时威望18024 UID379499阅读权限200精华0主题积分18024帖子金币138
今生相遇,是喜,是悲,全看老天
积分18024帖子金币138
LZ又是在找什么邪恶的东西吧....
注册时间最后登录在线时间43 小时威望355 UID384425阅读权限40精华0主题积分355帖子金币37
三星若人, 积分 355, 距离下一级还需 45 积分
积分355帖子金币37
写语文中 发表于
LZ又是在找什么邪恶的东西吧....
不是啊&&再找速度与激情5啊& &还有电驴也上不去&&怎么搞的?
注册时间最后登录在线时间706 小时威望21250 UID435100阅读权限120精华0主题积分21250帖子金币1891
七宗罪:饕餮、贪婪、纵欲、懒惰、嫉妒、骄傲、愤怒
一冠若人, 积分 21250, 距离下一级还需 18750 积分
积分21250帖子金币1891
我记得*好像是资源极度冷门,还有P2P连不上去可能是楼主你那的网络不稳定
注册时间最后登录在线时间43 小时威望355 UID384425阅读权限40精华0主题积分355帖子金币37
三星若人, 积分 355, 距离下一级还需 45 积分
积分355帖子金币37
我记得*好像是资源极度冷门,还有P2P连不上去可能是楼主你那的网络不稳定
好吧、我家网络很好的& &从来不卡& &迅雷下载普通会员都在200KB/s以上啊&&
注册时间最后登录在线时间43 小时威望355 UID384425阅读权限40精华0主题积分355帖子金币37
三星若人, 积分 355, 距离下一级还需 45 积分
积分355帖子金币37
网络温不稳定和迅雷下载速度没多大关系(个人认为)温不稳定看这两个电脑,一直亮着说明稳定急了,闪来闪去说 ...
额& &我家全亮啊& &没有闪啊
在线时间500小时以上
论坛元老级人物佩戴
论坛等级达到五钻若人
累计捐助2000金币以上
Powered by查看: 5929|回复: 43
【求助】全端口映射p2p问题
今天在nat123论坛看了一个应用类型可以为p2p开MC服务器的,我就测试了一下。
参照这位大大的教程。MCPC+文本里的server文本的server-ip=localhost了& &&&
QQ图片27.jpg (30.7 KB, 下载次数: 64)
16:30 上传
映射也设置这样了,也使用了访问者访问了。服务器也运行了。
难道这项类型是要钱的嘛?& &我让个人用nat123访问测试。输入IP:& &localhost:25565& && && &&&可对?
还是哪里错了泪?
好吧,我发现问题所在原因了.................这个只提供内网玩而已?这样...........
好吧,我发现问题所在原因了.................这个只提供内网玩而已?这样...........
如果是自己玩的话,直接用你本地IP就可以不用NAT123做映射的。
全端口映射后需要在所有访问端使用访问者进行访问。
好吧,我发现问题所在原因了.................这个只提供内网玩而已?这样...........
如果想把你的服务发布到外网的话,就需要NAT123对外做映射。我今天上网就给群里的一个朋友做的是P2P映射,速度很快。
看来还是你设置的问题。而且外网访问你服务的话,需要在访问端,启动NAT123访问者。
把你映射的外网的地址添加进去。
如果想把你的服务发布到外网的话,就需要NAT123对外做映射。我今天上网就给群里的一个朋友做的是P2P映射 ...
不懂你滴意思,我用访问者了啊...按照你写的教程测试了,
QQ图片50.jpg (3.28 KB, 下载次数: 49)
17:04 上传
还有我的是非固定ip
是不用固定ip的..
你下载安装最新版试试,p2p是不通100%穿透的,不过穿透率还是挺高的,后续会不断提升穿透率...你可以使用 全端口(转发+p2p)才是100%穿透的。。
是不用固定ip的..
你下载安装最新版试试,p2p是不通100%穿透的,不过穿透率还是挺高的,后续会不断提升穿 ...
我想说,这个p2p怎么发布外网让别人也能进呢?
Powered by
| 网站反馈邮箱:(把#换成@)p2p打洞成功,但ADSL网络用户收不到信息。
[问题点数:120分,结帖人jinghao666666]
p2p打洞成功,但ADSL网络用户收不到信息。
[问题点数:120分,结帖人jinghao666666]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2009年 总版技术专家分年内排行榜第四
2009年2月 总版技术专家分月排行榜第一2009年1月 总版技术专家分月排行榜第一2008年11月 总版技术专家分月排行榜第一2008年10月 总版技术专家分月排行榜第一2008年9月 总版技术专家分月排行榜第一2008年8月 总版技术专家分月排行榜第一2008年7月 总版技术专家分月排行榜第一2008年6月 总版技术专家分月排行榜第一2008年5月 总版技术专家分月排行榜第一2008年4月 总版技术专家分月排行榜第一
2009年 总版技术专家分年内排行榜第四
2009年2月 总版技术专家分月排行榜第一2009年1月 总版技术专家分月排行榜第一2008年11月 总版技术专家分月排行榜第一2008年10月 总版技术专家分月排行榜第一2008年9月 总版技术专家分月排行榜第一2008年8月 总版技术专家分月排行榜第一2008年7月 总版技术专家分月排行榜第一2008年6月 总版技术专家分月排行榜第一2008年5月 总版技术专家分月排行榜第一2008年4月 总版技术专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。