udp 穿透,内网服务器,已测原理代码。

package socket.Stun.simple.ns.s;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket; 
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.Timer;
import java.util.TimerTask;

public class S {

	/**
	 * @param args
	 * @throws IOException
	 */
	/**
	 * @param args
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws IOException,
			InterruptedException {

		final DatagramSocket udpsocket = new DatagramSocket(42000);
		udpsocket.setReuseAddress(true);
		System.out.println(" 等待NS注册和NC指令");
		// 等待NS注册和NC指令
		SocketAddress NSaddress = null;
		
		
		
		
		
		
		
		boolean end = false;
		try {
			while (end == false) {
				byte[] buf = new byte[1024];
				DatagramPacket udp = new DatagramPacket(buf, buf.length);
				udpsocket.receive(udp);
				String msg = new String(udp.getData());
				if (msg.startsWith("NS:")) {
					NSaddress = udp.getSocketAddress();
					System.out.println("收到来自NS" + NSaddress + "的注册");
					System.out.println(new String(udp.getData()));
					String respNS = "NS:" + udp.getAddress() + ":"
							+ udp.getPort();
					DatagramPacket repNSudp = new DatagramPacket(respNS
							.getBytes(), respNS.getBytes().length, NSaddress);
					udpsocket.send(repNSudp);
					udpsocket.send(repNSudp);
					udpsocket.send(repNSudp);

					// 检测客户端保持活动
					TimerTask checkNSalive = new TimerTask() {

						@Override
						public void run() {
							try {
								byte[] buf = new byte[1024];
								DatagramPacket udp = new DatagramPacket(buf,buf.length);
								udpsocket.receive(udp);
								System.out.println("收到客户端用来保持连接存活的消息:"+new String(udp.getData()));
							} catch (SocketException e) {
								e.printStackTrace();
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					};
					new Timer().schedule(checkNSalive, 0, 20 * 1000);
					
					
					
					System.out.println("输入S->NS的消息");
					BufferedReader localin = new BufferedReader(
							new InputStreamReader(System.in));
					respNS = null;
					while (respNS == null) {
						respNS = localin.readLine();
					}
					int moments = 6;
					while (true) {
						repNSudp = new DatagramPacket((respNS+":延迟"+moments+"分钟").getBytes(), (respNS+":延迟"+moments+"分钟")
								.getBytes().length, NSaddress);
						udpsocket.send(repNSudp);
						udpsocket.send(repNSudp);
						udpsocket.send(repNSudp); 
						Thread.sleep(60 * 1000 * moments);
						moments+=1; 
					}

				} else {
					System.out.println(new String(udp.getData()));
				}
			}
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
}

 

package socket.Stun.simple.ns.s;
 
import java.io.IOException; 
import java.net.DatagramPacket;
import java.net.DatagramSocket;  
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Timer;
import java.util.TimerTask;

public class NS {

	/**
	 * @param args
	 * @throws IOException
	 */
	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
 
		if(args.length<1){
			System.out.println("usage: NS 172.16.253.123");
			return;
		}
		String stunIp = args[0];
		int stunPort = 42000;
		final InetSocketAddress Saddress = new InetSocketAddress(stunIp, stunPort);
		final DatagramSocket udpsocket = new DatagramSocket(42001);  
		udpsocket.setReuseAddress(true);
		System.out.println("Sotimeout:"+udpsocket.getSoTimeout());
		String outAddress = null;
		String NSname = "NS:" ;
		DatagramPacket udp = new DatagramPacket(NSname.getBytes(), NSname
				.getBytes().length, Saddress);
		udpsocket.send(udp);
		udpsocket.send(udp);
		udpsocket.send(udp);
		while (true) {
			byte[] buf = new byte[1024];
			DatagramPacket reged = new DatagramPacket(buf, buf.length);
			udpsocket.receive(reged);
			System.out.println("收到消息。");
			if(udp.getSocketAddress().equals(Saddress)){

				System.out.println("\t收到S的消息。");
				outAddress = new String(udp.getData());
				
				
				
				if (outAddress.startsWith("NS:")) {
					System.out.println("\t\t收到S确认注册的消息。");
					outAddress = outAddress.substring(3); 
					break;
				}
			}
		}
		System.out.println("注册成功。外网地址为:" + outAddress);

		// 2保持映射活动
		TimerTask keepalive = new TimerTask() {

			@Override
			public void run() {
				try {
					DatagramPacket udp = new DatagramPacket("NS:hello S,"
							.getBytes(), "hello S,".getBytes().length,
							Saddress); 
					udpsocket.send(udp);
					System.out.println("keepalive");
				} catch (SocketException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};
		new Timer().schedule(keepalive, 0, 20 * 1000);

		// 3等待指令S->NS  
		while (true) {
			byte[] buf = new byte[1024];
			udp = new DatagramPacket(buf, buf.length);
			udpsocket.receive(udp);
			if (udp.getSocketAddress().equals(Saddress)) {
				System.out.println("收到" + udp.getSocketAddress() + "的数据:"
						+ new String(udp.getData()));

				String msg = new String(udp.getData());
				System.out.println("S:"+msg);
			}
		}
	 
		

	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值