UDP打洞原理,Delphi演示

上传人:飞*** 文档编号:28277553 上传时间:2018-01-16 格式:DOC 页数:5 大小:32.50KB
返回 下载 相关 举报
UDP打洞原理,Delphi演示_第1页
第1页 / 共5页
UDP打洞原理,Delphi演示_第2页
第2页 / 共5页
UDP打洞原理,Delphi演示_第3页
第3页 / 共5页
UDP打洞原理,Delphi演示_第4页
第4页 / 共5页
UDP打洞原理,Delphi演示_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

《UDP打洞原理,Delphi演示》由会员分享,可在线阅读,更多相关《UDP打洞原理,Delphi演示(5页珍藏版)》请在金锄头文库上搜索。

1、 UDP 打洞原理,Delphi 演示1. NAT 分类根据 Stun 协议(RFC3489),NAT 大致分为下面四类1) Full Cone这种 NAT 内部的机器 A 连接过外网机器 C 后,NAT 会打开一个端口 .然后外网的任何发到这个打开的端口的 UDP 数据报都可以到达 A.不管是不是 C 发过来的.例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88A(192.168.8.100:5000) - NAT(202.100.100.100 : 8000) - C(292.88.88.88:2000)任何发送到 NAT(202.1

2、00.100.100:8000)的数据都可以到达 A(192.168.8.100:5000)2) Restricted Cone这种 NAT 内部的机器 A 连接过外网的机器 C 后,NAT 打开一个端口 .然后 C 可以用任何端口和A 通信.其他的外网机器不行 .例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88A(192.168.8.100:5000) - NAT(202.100.100.100 : 8000) - C(292.88.88.88:2000)任何从 C 发送到 NAT(202.100.100.100:8000)的数据都可

3、以到达 A(192.168.8.100:5000)3) Port Restricted Cone这种 NAT 内部的机器 A 连接过外网的机器 C 后,NAT 打开一个端口 .然后 C 可以用原来的端口和 A 通信.其他的外网机器不行 .例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88A(192.168.8.100:5000) - NAT(202.100.100.100 : 8000) - C(292.88.88.88:2000)C(202.88.88.88:2000)发送到 NAT(202.100.100.100:8000)的数据都可

4、以到达A(192.168.8.100:5000)以上三种 NAT 通称 Cone NAT.我们只能用这种 NAT 进行 UDP 打洞.4) Symmetic对于这种 NAT.连接不同的外部目标 .原来 NAT 打开的端口会变化 .而 Cone NAT 不会.虽然可以用端口猜测.但是成功的概率很小.因此放弃这种 NAT 的 UDP 打洞.2. UDP hole punching对于 Cone NAT.要采用 UDP 打洞.需要一个公网机器 C 来充当”介绍人”.内网的 A,B 先分别和C 通信.打开各自的 NAT 端口.C 这个时候知道 A,B 的公网 IP: Port. 现在 A 和 B 想直

5、接连接.比如 A 给 B 发.除非 B 是 Full Cone.否则不能通信.反之亦然.但是我们可以这样.A 要连接 B.A 给 B 发一个 UDP 包.同时.A 让那个介绍人给 B 发一个命令,让 B 同时给 A 发一个UDP 包 .这样双方的 NAT 都会记录对方的 IP,然后就会允许互相通信 .3. 同一个 NAT 后面的情况如果 A,B 在同一个 NAT 后面 .如果用上面的技术来进行互连 .那么如果 NAT 支持 loopback(就是本地到本地的转换),A,B 可以连接 ,但是比较浪费带宽和 NAT.有一种办法是,A,B 和介绍人通信的时候,同时把自己的 local IP 也告诉服

6、务器.A,B 通信的时候,同时发 local ip 和公网 IP.谁先到就用哪个 IP.但是 local ip 就有可能不知道发到什么地方去了.比如 A,B 在不同的 NAT 后面但是他们各自的 local ip 段一样.A 给 B 的 local IP 发的 UDP 就可能发给自己内部网里面的某某某了.还有一个办法是服务器来判断 A,B 是否在一个 NAT 后面 .(网络拓朴不同会不会有问题?)下面放一个外网服务器与内网客户机传数据例子 Delphi 7.0 +Windows XP ProUDPP2PSer.dpr程序代码2009-5-6 客户端UDP 打洞演示,P2P 应用,只是简单演示在

7、些就不作容错检查了HouSoft 一人游走 Http:/Www.YrYz.Netprogram UDPP2PSer;$APPTYPE CONSOLEuseswindows, SysUtils, winsock;constSER_PORT = 20956;varwsaData: TWSADATA;Sock: TSocket;ListAddr: TSockAddrIn;Thid: DWORD;s: string;procedure WorkThread;varAddr: TSockAddrIn;len, Num: integer;Buf: array0.1023 of char;beginNum

8、:= 0;len := sizeof(Addr);Writeln(开始接收.);while true do beginFillChar(Buf, sizeof(Buf), #0);if recvfrom(Sock, Buf, sizeof(Buf), 0, Addr, len) SOCKET_ERROR then beginInc(Num); /Inet_ntoa(Addr.sin_addr) ntohs(Addr.sin_port 内网客户端的 NAT 地址和端口,将作为服务器发数据的目地地址和端口Writeln(Revc: + Inet_ntoa(Addr.sin_addr) + : +

9、IntToStr(ntohs(Addr.sin_port) + #9 + Buf);/返回数据到客户端StrPCopy(Buf, Format(Time:%s Index:%d NatIP:%s NatPort:%d, FormatDateTime(hh:mm:ss.zzz, now(), Num, Inet_ntoa(Addr.sin_addr), ntohs(Addr.sin_port);if sendto(Sock, Buf, sizeof(Buf), 0, Addr, len) SOCKET_ERROR thenWriteln(IntToStr(Num) + .回送 OK!);ende

10、lsebreak;end;end;beginWSAStartUp($0202, wsaData);Sock := Socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);ListAddr.sin_family := AF_INET;ListAddr.sin_addr.S_addr := htonl(INADDR_ANY);ListAddr.sin_port := htons(SER_PORT);if bind(Sock, ListAddr, sizeof(ListAddr) SOCKET_ERROR then beginWriteln(创建服务成功 端口 : + Int

11、ToStr(ntohs(ListAddr.sin_port);CreateTHread(nil, 0, WorkThread, nil, 0, Thid);while true do beginreadln(s);if s = e then halt;Writeln(Send Bytes: + IntToStr(sendto(Sock, s1, Length(s), 0, ListAddr, sizeof(ListAddr);end;end;WSACleanup;end.UDPP2PCli.dpr程序代码2009-5-6 客户端UDP 打洞演示,P2P 应用,只是简单演示在些就不作容错检查了H

12、ouSoft 一人游走 Http:/Www.YrYz.Netprogram UDPP2PCli;$APPTYPE CONSOLEuseswindows, SysUtils, winsock;constSER_IP = 58.54.188.103;SER_PORT = 20956;varwsaData: TWSADATA;Sock: TSocket;ListAddr: TSockAddrIn;Thid: DWORD;s: string = HouSoft 一人游走 Http:/Www.YrYz.Net;Num: integer;procedure WorkThread;varAddr: TSoc

13、kAddrIn;len: integer;Buf: array0.1023 of char;beginNum := 0;len := sizeof(Addr);Writeln(开始接收.);while true do beginFillChar(Buf, sizeof(Buf), #0);if recvfrom(Sock, Buf, sizeof(Buf), 0, Addr, len) SOCKET_ERROR then beginInc(Num);Writeln(IntToStr(Num) + .Revc: + Inet_ntoa(Addr.sin_addr) + : + IntToStr(

14、ntohs(Addr.sin_port) + #9 + Buf);endelsebreak;end;end;beginWSAStartUp($0202, wsaData);Sock := Socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);ListAddr.sin_family := AF_INET;ListAddr.sin_addr.S_addr := htonl(INADDR_ANY);ListAddr.sin_port := htons(SER_PORT);if bind(Sock, ListAddr, sizeof(ListAddr) SOCKET_ERRO

15、R then beginWriteln(创建客户成功 端口 : + IntToStr(ntohs(ListAddr.sin_port);CreateTHread(nil, 0, WorkThread, nil, 0, Thid);ListAddr.sin_addr.S_addr := Inet_Addr(SER_IP); /服务 IPListAddr.sin_port := htons(SER_PORT); /服务端口while true do begin/注意,发送 Sock 也是接收 Sock 这样数据才能正常返回Writeln(Send Bytes: + IntToStr(sendto(Sock, s1, Length(s), 0, ListAddr, sizeof(ListAddr);sleep(1000);end;end;WSACleanup;end.

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号