内网穿透实现 服务端:(如腾讯服务器) import java.net.*; import java.io.*; import java.util.*; public class DatagramRouteServer { private Set<InetSocketAddress> clientAddSet=new HashSet(); //该容器存放所有客户端的地址 //启动UDP服务器,接收消息,转发消息 public void startServer()throws Exception{ DatagramSocket socket=new DatagramSocket(9090); System.out.println("UDP服务器等待接收数据:"+socket.getLocalAddress()); while(true){ byte[] buffer=new byte[256]; //创建数据包 DatagramPacket packet=new DatagramPacket(buffer,buffer.length); socket.receive(packet); //得到发送方IP和端口 InetAddress clientAdd=packet.getAddress(); int clientPort=packet.getPort(); InetSocketAddress address=new InetSocketAddress(clientAdd,clientPort); //将这个地址加入到Set中 clientAddSet.add(address); //提取发送内容 byte[] recvData=packet.getData(); String s=new String(recvData).trim(); System.out.println("服务器收到数据:"+s+" 来自:"+address); //给Set中的每一个地址发送信息,信息内容为新登入服务器的发送方来取地址了 for(InetSocketAddress dclient:clientAddSet){ String temf=address+",到服务器取地址了"; //转发服务器端的地址列表数据 ByteArrayOutputStream bous=new ByteArrayOutputStream(); ObjectOutputStream oos=new ObjectOutputStream(bous); oos.writeObject(temf); //这里是字符串 oos.flush(); byte[] data=bous.toByteArray(); DatagramPacket mp=new DatagramPacket(data,data.length); mp.setSocketAddress(dclient); //DatagramPacket mp=new DatagramPacket(data,data.length,dclient); socket.send(mp); } ByteArrayOutputStream bous=new ByteArrayOutputStream(); ObjectOutputStream oos=new ObjectOutputStream(bous); oos.writeObject(clientAddSet); //将一个Set写入了流中。object包装过了 。和上面的都是Object强制转换的,故接收时要判断 oos.flush(); byte[] data=bous.toByteArray(); DatagramPacket sendP=new DatagramPacket(data,data.length); sendP.setSocketAddress(address); socket.send(sendP); } } public static void main(String[] arg) throws Exception{ new DatagramRouteServer().startServer(); } } 客户端(如QQA用户和QQB用户) import java.net.*; import java.io.*; import java.util.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class DatagramNetClient extends Thread{ //公网服务器地址 private SocketAddress destAdd=new InetSocketAddress("172.16.1.25",9090); private DatagramSocket sendSocket; //构造函数里初始化 //显示消息的文本框 private JTextArea jta_recive=new JTextArea(10,50); //10*25 //显示其他的客户地址 private JComboBox jta_addList=new JComboBox(); public DatagramNetClient(){ try{ sendSocket=new DatagramSocket(); }catch(Exception e){ e.printStackTrace(); } } @Override public void run() { try{ while(true){ byte[] recvData=new byte[2048]; DatagramPacket recvPacket=new DatagramPacket(recvData,recvData.length); sendSocket.receive(recvPacket); byte[] data=recvPacket.getData(); //收到的是Set中的ip地址,应该也是个对象流 //读取信息 ByteArrayInputStream bins=new ByteArrayInputStream(data); ObjectInputStream oins=new ObjectInputStream(bins); Object dataO=oins.readObject(); //收到的是两种信息 if(dataO instanceof Set){ Set<InetSocketAddress> othersAdds=(Set)dataO; jta_addList.removeAllItems(); for(InetSocketAddress it:othersAdds){ jta_addList.addItem(it); } }else if(dataO instanceof String){ String s=(String)dataO; System.out.println(s+" "); }else{ String s="unkown msg:"+dataO; jta_recive.append(s+" "); } } }catch(Exception e){ e.printStackTrace(); } } public void setUpUI(){ JFrame jf=new JFrame("p2p测试-客户端"); jf.setLayout(new FlowLayout()); jf.setSize(500,400); JButton jb_get=new JButton("获取其他客户端地址"); jf.add(jb_get); jf.add(jta_addList); jb_get.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { sendRequestMsg("取得地址"); }}); JLabel la_name=new JLabel("接收到的信息:"); JLabel la_users=new JLabel("发送给:"); final JTextField jtf_send=new JTextField(20); //发送输入框 JButton bu_send=new JButton("发送"); JScrollPane js=new JScrollPane(jta_recive); jf.add(la_name); jf.add(js); jf.add(la_users); jf.add(jtf_send); jf.add(bu_send); ActionListener sendListener=new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { String msg=jtf_send.getText(); InetSocketAddress dest=(InetSocketAddress)jta_addList.getSelectedItem(); //核心代码!! sendP2PMsg(msg,dest); jtf_send.setText(""); } }; bu_send.addActionListener(sendListener); jtf_send.addActionListener(sendListener); jf.setVisible(true); jf.setDefaultCloseOperation(3); } public void sendRequestMsg(String msg){ try{ byte[] buffer=msg.getBytes(); DatagramPacket dp=new DatagramPacket(buffer,buffer.length,destAdd); sendSocket.send(dp); }catch(Exception e){ e.printStackTrace(); } } public void sendP2PMsg(String msg,InetSocketAddress dest){ try{ ByteArrayOutputStream bous=new ByteArrayOutputStream(); ObjectOutputStream oos=new ObjectOutputStream(bous); oos.writeObject(msg); byte[] buffer=bous.toByteArray(); DatagramPacket dp=new DatagramPacket(buffer,buffer.length,dest); sendSocket.send(dp); }catch(Exception e){ e.printStackTrace(); } } public static void main(String[] args){ DatagramNetClient sender=new DatagramNetClient(); sender.start(); sender.setUpUI(); } } |
|