日期:2014-05-18  浏览次数:21179 次

关于 UDP打洞~~
内网PC A  
内网PC B

需要A和B 能够socket通讯 现了解 需要打洞借助
server C

由A发送信息到C C再告诉B 往A 打洞,
然后A就可以和B通讯了,

问题来了:
1.我上面说的对不对,如果不对应该是什么样的。
2.C 如何 告诉B要向A打洞 ,然后B 又是如何 向A 打洞的 ,C#里应该是什么函数实现的,
3.洞打通了,A 要向B 发送信息,需要指定的IP和端口是怎么获取的,通过什么函数可以获取

------解决方案--------------------
这样也行?坐等牛人

------解决方案--------------------
A向C发消息,C获得A的IP地址和端口,
B向C发消息,C获得B的IP地址和端口,
C把B的IP地址和端口告诉A,
C把A的IP地址和端口告诉B,
A向B的IP地址和端口发送消息,同时B向A的IP地址和端口发送消息

c#的udp发送函数为socket.sendto或者socket.sendtoasync或者socket.beginsendto;
接受函数为socket.receivefrom或者socket.receivefromasync或者socket.beginreceivefrom

C服务端通过socket.receive系列函数的参数可以获得客户端的IP地址和端口号
------解决方案--------------------
楼主,你的需求中能不能在C上放个转发的啊? 我以为是不放的。。。
------解决方案--------------------
我补充一下#4楼的描述:

实际上A先访问C,然后尝试访问B;B先访问C,然后尝试访问A。这里边关键是,两次访问时本定绑定的端口一定要相同。实际上tcp也是可以端口复用的,只是编程上要多写几条语句,而且(可能)更容易在通讯时失败,所以大多数人打洞都是用udp。你在new一个udpclient对象之后,在绑定本地端口不变的情况下,分别需要访问C,然后访问B,因此这就属于“无连接的Send”,既不调用udpclient对象的connect操作而直接发送数据。

C在收到消息时,通过remoteEP参数获得对方外网的IP和端口。

A与C、B与C实际上保持长连接,双向通讯,因此(使用你自己定义的信令协议中的几个命令)A既告诉C要连接B,又要接收C返回的有关B的外网IP和端口的信息。

当“A向B的地址和端口发送消息”时,必定失败。因为B的路由器不允许A主动访问B。但是此时,A的路由器为B的访问而打开了,所有下一个“B向A的地址和端口发送消息”时A就收到了B的消息。

A与B之间要保持长连接,要频繁相互发送心跳消息,否则A的路由器就会切断你打的洞。
------解决方案--------------------
如果Nat类型是Cone或受限的(Restricted),借助第三方是可以打洞的,但如果是对称的(Symmetric)就没戏了,只能利用一些具有公网IP的机器转发。
------解决方案--------------------
tcp打洞的成功率不高,大多数nat都无法穿越。
客户端创建socket后,设置允许复用,然后用该socket连接服务器,服务器取得客户端的地址后断开连接,客户端立即listen该socket,并接受连接;服务器将地址通知另一客户端,由该客户端发起连接