搜索了一下,基本没有C#的代码可供参考,
有的完全依靠服务端转发数据。
还有乱贴代码没有测试勿人子弟一大群。废话就算了,言归正卷了。
假设A要和B之间通讯(AB均在不同路由下),必须借助S进行沟通调节.
A连接B,的步骤就是A先告诉S我要连接B,S传话给B有个小子要和你单挑,B对A的路由说放马过来吧,A马上向B的路由发送单条信息。(这个过程参照网上的说法总结,不知道对不对)现在有个问题了
A,B和S的连接必须是TCP连接,。(我想应该是的,要不怎么去及时去给A,B传话)
B对A的路由说放马过来,但是它应该对那个路由端口说呢??
A又向B的路由发信息,它又应该对那个端口说呢??
A和B都不知道路由开的是那个端口。
有的完全依靠服务端转发数据。
还有乱贴代码没有测试勿人子弟一大群。废话就算了,言归正卷了。
假设A要和B之间通讯(AB均在不同路由下),必须借助S进行沟通调节.
A连接B,的步骤就是A先告诉S我要连接B,S传话给B有个小子要和你单挑,B对A的路由说放马过来吧,A马上向B的路由发送单条信息。(这个过程参照网上的说法总结,不知道对不对)现在有个问题了
A,B和S的连接必须是TCP连接,。(我想应该是的,要不怎么去及时去给A,B传话)
B对A的路由说放马过来,但是它应该对那个路由端口说呢??
A又向B的路由发信息,它又应该对那个端口说呢??
A和B都不知道路由开的是那个端口。
这个端口应该不是路由的端口吧.是程序运行那台机器开放的端口吧.
必须是TCP连接的?不是必须吧?要不怎么叫UDP穿透呢?
B向S发一个新连接,,S把B路由的端口发送到A,
A向B路由的端口发送测试连接,同时向后续的10个端口发,
B向A路由的端口发测试连接,同时向后续10个端口发,
理论上应该有一定机会碰到,不过不用测试就知道在大规模应用中绝对是垃圾方法。
因为路由也不是为你个人服务的。
位于不同的网络之间的机器无法直接通信,除非借助于一台Server,
也就是你说的这个中间机器,
两台client不需要知道互相之间的信息,
所必须的是,两台机器如何和服务器通信。
回想以前我做的..大约是这样.
A,B,启动时向S登记自已的信息..如是内网则是公网的ip地址加路由随机的端口号.
因为处于路由后面的机器不能和另一个处于路由后面的机器通话.所以要通过一个有公网地址的(服务器)中转一下.
A 想和B通话.就发个信息给S要它中转下.S收到信息后.把A的IP地址与端口告诉B.B根据这个信息向A发个信息.
由于时延.可以在A向S发个请求信息后.有个时延.然后再向B发信息.大约是这样..希望不会再记错.
BeginReceive,不需要关心时间的延迟,应为你根本不知道
数据会什么时候反应过来,因为Server可能会处理很多客户端
你的数据在Server上可能需要排队,
A、B登录后均要向S报告自己的位置和端口,
S还要定期对登录的用户点名,以便知道还在不在线。
S判断A、B是不是都在线,如果都在线则通知他们自己去P2P,否则暂存在线的一方发来的消息,等另一方登录后发给他
A、B登录后均要向S报告自己的位置和端口,
S还要定期对登录的用户点名,以便知道还在不在线。
S判断A、B是不是都在线,如果都在线则通知他们自己去P2P,否则暂存在线的一方发来的消息,等另一方登录后发给他
问题是路由不像我们自己的电脑分配端口自己可以知道,这里每次分配的端口只有通过S知道了,但是S只知道这次通讯的端口,怎么知道A准备跟B通讯的端口呢,又重新分配呢一个呀。总不能一个一个的试吧(也就是我上面提到的试着连接后续的10个端口看是否能连接上)。
A与B都要连接服务器C。
A与B通信。那么A首先要向B发出一个连接,这时候NAT会记录下这个向B去的IP端口,当然了,到B会被阻止,但是在A这边会保存在NAT列表里一段时间。现在才是把A连向B出去那个地址发给C,由C发给B,这样B才可以A建立通信。
A与B都要连接服务器C。
A与B通信。那么A首先要向B发出一个连接,这时候NAT会记录下这个向B去的IP端口,当然了,到B会被阻止,但是在A这边会保存在NAT列表里一段时间。现在才是把A连向B出去那个地址发给C,由C发给B,这样B才可以A建立通信。A与B通信。那么A首先要向B发出一个连接(问题是A向B的什么端口发,目前唯一能知道的是B跟C通讯的路由端口,不会是B跟C通讯的端口吧,这个时候B的路由路由绝对会阻止A的连接,确实A的路由有记录,但记录的是A连接B的一个与C连接的端口,这个时候如果你能保证B能用B跟C通讯的端口发信息给A就没有如何问题,但实际你拿什么保证路由器会一定把那个跟C的端口给你用??)
NAT A 记录 202.103.2.123:60000---202.103.1.123:8000B---C 192.168.1.1:4000
NAT B 记录 202.103.3.123:30000---202.103.1.123:8000照wmhnq() 的说法
A 向B 发连接
A---B 202.103.1.123:8000
NAT A 记录 202.103.2.123:?(不确定)---202.103.1.123:8000(这边阻止呢)
A也得不到NAT A的202.103.2.123:?(不确定)怎么告诉C,它自己只知道开了一个192.168.0.1:4001去连接202.103.1.123:8000失败了。
NAT A 记录 202.103.2.123:60000---202.103.1.123:8000B---C 192.168.1.1:4000
NAT B 记录 202.103.3.123:30000---202.103.1.123:8000照wmhnq() 的说法
A 向B 发连接
A---B 202.103.3.123:30000
NAT A 记录 202.103.2.123:?(不确定)---202.103.3.123:30000(这边阻止呢)
A也得不到NAT A的202.103.2.123:?(不确定)怎么告诉C,它自己只知道开了一个192.168.0.1:4001去连接202.103.3.123:30000失败了。
A与B已经连上服务器C。
现在A与B想通信,
A开始向B发出连接,这个时候通知服务器让B也连向A,双方的NAT列表都有彼此了。那么就可以连通了。
A与B已经连上服务器C。
现在A与B想通信,
A开始向B发出连接,这个时候通知服务器让B也连向A,双方的NAT列表都有彼此了。那么就可以连通了。
----------------
A B 已经连接上C 只能得到 A B 局域网ip和端口 和AB 所占用的 各自路由器 ip和端口 对吧。
A开始向B发出连接,这个时候通知服务器让B也连向A,双方的NAT列表都有彼此了。那么就可以连通了,这一步就有问题了,A向B发的连接是什么?我想唯一能知道的就是B占用路由的IP和端口,但是却得不到现在A重新占用路由器A的新开端口了。如果A的路由器和B的路由器始终用相同的端口来向其它地址发信息就没有问题了。但问题是它会继续分配新的端口。而这个新的端口A自己的不到,B这个时候又链不上,当然就得不到。
http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt
里我看不懂,大概说得就是这个意思Ford, Srisuresh & Kegel [Page 15]
Internet-Draft P2P applications across middleboxes October 2003
A-S 155.99.25.11:62000 B-S 138.76.29.7:31000
| |
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234 NAT A has assigned its own UDP port 62000 to the communication
session between A and S, and NAT B has assigned its port 31000 to the
session between B and S. By communicating through server S, A and B
learn each other's public IP addresses and port numbers as observed
by S. Client A now starts sending UDP messages to port 31001 at
address 138.76.29.7 (note the port number increment), and client B
simultaneously starts sending messages to port 62001 at address
155.99.25.11. If NATs A and B assign port numbers to new sessions
sequentially, and if not much time has passed since the A-S and B-S
sessions were initiated, then a working bi-directional communication
channel between A and B should result. A's messages to B cause NAT A
to open up a new session, to which NAT A will (hopefully) assign
public port number 62001, because 62001 is next in sequence after the
port number 62000 it previously assigned to the session between A and
S. Similarly, B's messages to A will cause NAT B to open a new
session, to which it will (hopefully) assign port number 31001. If
both clients have correctly guessed the port numbers each NAT assigns
to the new sessions, then a bi-directional UDP communication channel
will have been established as shown below. Server S
18.181.0.31:1234
|
|
+----------------------+----------------------+
| |
NAT A NAT B
A-S 155.99.25.11:62000 B-S 138.76.29.7:31000
A-B 155.99.25.11:62001 B-A 138.76.29.7:31001
| |
| |
Client A Client B
10.0.0.1:1234 10.1.1.3:1234 Obviously there are many things that can cause this trick to fail.
If the predicted port number at either NAT already happens to be in
use by an unrelated session, then the NAT will skip over that port
number and the connection attempt will fail. If either NAT sometimes
or always chooses port numbers non-sequentially, then the trick will
fail. If a different client behind NAT A (or B respectively) opens
up a new outgoing UDP connection to any external destination after A
(B) establishes its connection with S but before sending its firstFord, Srisuresh & Kegel [Page 16]
A与B已经连上服务器C。
现在A与B想通信,
A开始向B发出连接,连B的哪里,我靠,你B连到C是什么IP端口,就连什么。
这个时候通知服务器让B也连向A,我靠,你A连到C是什么IP端口,就连什么。
双方的NAT列表都有彼此了。
那么就可以连通了。
有四种方式可以实现:1:NAT/ALG 方式 NAT/ALG是支持VOIP NAT穿透的一种最简单的方式,但由于网络实际情况是已部署了大量的不支持此种特性的NAT/FW设备,因此,实际应用中,很难采用这种方式。2:MIDCOM 方式 3:STUN 方式 解决穿透NAT问题的另一思路是,私网中的VOIP终端通过某种机制预先得到出口NAT上的对外地址,然后在净载中所填写的地址信息直接填写出口NAT上的对外地址,而不是私网内终端的私有IP地址,这样净载中的内容在经过NAT时就无需被修改了,只需按普通NAT流程转换报文头的IP地址即可,净载中的 IP地址信息和报文头地址信息是一致的。STUN协议就是基于此思路来解决应用层地址的转换问题。TURN方式4:TURN方式解决NAT问题的思路与STUN相似,也是私网中的VOIP终端通过某种机制预先得公网上的服务地址(STUN方式得到的地址为出口NAT上外部地址,TURN方式得到地址为TURN Server上的公网地址),然后在报文净载中所要求的地址信息就直接填写该公网地址。
看看下面的情况:
Server S1 Server S2
18.181.0.31:1235 138.76.29.7:1235
| |
| |
+----------------------+----------------------+
|
^ Session 1 (A-S1) ^ | ^ Session 2 (A-S2) ^
| 18.181.0.31:1235 | | | 138.76.29.7:1235 |
v 155.99.25.11:62000 v | v 155.99.25.11:62000 v
|
Cone NAT
155.99.25.11
|
^ Session 1 (A-S1) ^ | ^ Session 2 (A-S2) ^
| 18.181.0.31:1235 | | | 138.76.29.7:1235 |
v 10.0.0.1:1234 v | v 10.0.0.1:1234 v
|
Client A
10.0.0.1:1234
接上面的例子,如果Client A的原来那个Socket(绑定了1234端口的那个UDP Socket)又接着向另外一个Server S2发送了一个UDP包,那么这个UDP包在通过NAT时会怎么样呢?
这时可能会有两种情况发生,一种是NAT再次创建一个Session,并且再次为这个Session分配一个端口号(比如:62001)。另外一种是NAT再次创建一个Session,但是不会新分配一个端口号,而是用原来分配的端口号62000。前一种NAT叫做Symmetric NAT,后一种叫做Cone NAT。我们期望我们的NAT是第二种,呵呵,如果你的NAT刚好是第一种,那么很可能会有很多P2P软件失灵。(可以庆幸的是,现在绝大多数的NAT属于后者,即Cone NAT)算了,我已经知道原因了,可能我的开发环境叫做Symmetric NAT 吧
上面你们回答一直回避了一个问题,就是A 连 C 时 和 A 连 B 时 可能NAT A 用相同的端口而且不变的,但是有的时候它又换了一个新端口,而这点取决NAT 本身。A 或 B 都 不会能决定下次它用那个端口。
------------------------------
物理:HUB,网线
链路:MAC,ARP,交换机
网络:IP,ICMP,IGMP,路由器
传输:TCP,UDP
会话:HTTP,SMTP,FTP,POP3
表示:SOAP,SSL
应用:WebService的Method
-------------------------------
这些老大们生活在不同的世界,
对与交换机对话要用MAC地址与ARP协议
与路由器对话要用IP封包协议
机器间对话要用TCP,UDP,当然还有好多(Ping类的例外,他用ICMP)
——————————————————————————————————————————
不太相信。
UDP打洞,关键就是UDP洞点对点,单向。
所以嘛,A想揍扁B,不能随便去揍,B得先对A说你放马过来,A才能过来揍他。
那么B怎么知道A要去揍他呢?哦。A请S转告B:我要揍你!