本示例包括两个客户端UDPClient和MyServer。UDPClient发送数据到MyServer,MyServer负责接收数据。可传输文本、视频、音频、图片等。
最近我在学习这一块,写个例子。
(注:如果要在不同PC间运行,请修改UDPclient中的环回地址为测试server的真实ip地址,并关闭双方的windows defender。2017-04-10)
UDPClient端源代码:
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Font; import java.awt.GridLayout; import java.io.File; import java.io.FileInputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Timer; import java.util.TimerTask; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import javax.swing.SwingConstants; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class UDPClient extends JFrame { private JPanel pane = new JPanel();//防止jbutton的面板 private JButton button_send=new JButton ("选择并发送文件"); private JLabel label_client_ip = new JLabel("本机ip:",JLabel.CENTER); private JLabel label_server_ip = new JLabel("目标ip:",JLabel.CENTER); private JLabel label_client_port = new JLabel("本机端口:6000",JLabel.CENTER); private JLabel label_server_port = new JLabel("目标端口:10000",JLabel.CENTER); private JLabel label_file_state = new JLabel("文件当前状态:无任务",JLabel.CENTER); private InetAddress client_ip = null;//本机ip private InetAddress server_ip = null;//目标ip private int client_port;//本机port private int server_port;//目标port最小值 DatagramSocket socket_ack;//监听服务器端返回ack or nak String filename = null; File file ;//传送的文件 /** * Create the frame. * @param client_name : the title of this application * @param server_ip : destination ip * @param client_port : my port * @param server_port : destination port */ public UDPClient(String client_name ,String ip,int myport,int otherport ) { super (client_name);//程序标题栏 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口操作 setBounds(100, 100, 400, 500);//设置窗口大小 getContentPane().setLayout(new GridLayout (6,1,7,7)); //设置全局字体 Font font = new Font("楷体",Font.PLAIN,20); label_client_ip.setFont(font); label_server_ip.setFont(font); label_client_port.setFont(font); label_server_port.setFont(font); label_file_state.setFont(font); button_send.setBackground(Color.LIGHT_GRAY); button_send.setFont(font); //在面板上放置组件 getContentPane().add(label_client_ip); getContentPane().add(label_server_ip); getContentPane().add(label_client_port); getContentPane().add(label_server_port); getContentPane().add(pane); pane.add(button_send); getContentPane().add(label_file_state); this.setVisible(true); this.server_port=otherport;//获得目标端口 this.client_port=myport;//获得发送端口 /* * 给button_send增加监听事件addActionListener */ button_send.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { // 选择要发送的文件 JFileChooser filechooser = new JFileChooser(); int result = filechooser.showOpenDialog(UDPClient.this); if (result == JFileChooser.APPROVE_OPTION) { try{ File file1 = filechooser.getSelectedFile();//选择的文件 file=file1; try{ //将文件名发送过去 String filename1 = file1.getName();// 文件名 String tip = "有文件,请接收:" + filename1; byte[] fileNameBuf = tip.getBytes();// 字节buf DatagramSocket socket = new DatagramSocket(); DatagramPacket packet = new DatagramPacket(//封装packet fileNameBuf, fileNameBuf.length, UDPClient.this.server_ip, UDPClient.this.server_port); socket.send(packet);//发送 System.out.println(new String(packet.getData())); //socket.close(); UDPClient.this.label_file_state.setText("文件当前状态:文件正在传输..."); //将文件写入内存 FileInputStream fis=new FileInputStream(file); //发送文件长度 int filelen=fis.available(); String filelenStr=""+filelen; byte[] filelenBuf=filelenStr.getBytes(); //DatagramSocket socket = new DatagramSocket(); packet = new DatagramPacket(filelenBuf,filelenBuf.length,server_ip,UDPClient.this.server_port+1); socket.send(packet); System.out.println(new String(packet.getData())); //socket.close(); //发送文件主体 byte[] buffer = new byte[1024]; int blocknum=filelen/buffer.length;//将文件分成1024个字节的block,blocknum是块的个数,即循环次数 int lastsize=filelen%buffer.length;//最后一个packet的字节数 //socket=new DatagramSocket(); for (int i=0;i<blocknum;i++){ fis.read(buffer, 0, buffer.length);//从文件流读入buf中 packet=new DatagramPacket(buffer,buffer.length,server_ip,UDPClient.this.server_port+2); socket.send(packet); System.out.println(new String(packet.getData())); Thread.sleep(1);//简单的防止丢包 } //发送最后一个block的内容 fis.read(buffer, 0, lastsize); packet=new DatagramPacket(buffer,buffer.length,server_ip,UDPClient.this.server_port+2); socket.send(packet); System.out.println(new String(packet.getData())); Thread.sleep(1); //关闭fis和socket fis.close(); socket.close(); UDPClient.this.label_file_state.setText("文件当前状态:文件传输完毕。"); UDPClient.this.label_file_state.setText("文件当前状态::无任务"); } catch (Exception e1){ System.out.println(e1); } } catch (Exception ex){ JOptionPane.showMessageDialog(UDPClient.this, "打开文档出错!"); } } } }); try{ //获得本机ip , 目标ip this.client_ip=InetAddress.getLocalHost(); this.server_ip=InetAddress.getByName(ip); label_client_ip.setText("本机ip:"+this.client_ip.getHostAddress());//显示在面板上 label_server_ip.setText("目标ip:"+this.server_ip.getHostAddress());//显示在面板上 System.out.println(this.server_ip.getHostAddress()); } catch (Exception ex){ System.out.println(ex); } } /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { UDPClient client = new UDPClient("UDPClient","127.0.0.1",6000,10000); client.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } }
MyServer端源代码:
import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketAddress; import java.sql.Date; import java.text.SimpleDateFormat; import java.util.Timer; import java.util.TimerTask; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.WindowConstants; import java.awt.*; import javax.swing.*; import java.awt.event.*; public class MyServer extends JFrame { // 添加属性 private JPanel panel = new JPanel(); private JButton button_receive = new JButton("另存为"); private JLabel label_fileState = new JLabel("当前状态:无任务", JLabel.CENTER); private JLabel label_cip=new JLabel("本 机ip:",JLabel.CENTER); private JLabel label_sip=new JLabel("服务器ip:",JLabel.CENTER); private JLabel label_cport = new JLabel("本机端口:10000",JLabel.CENTER); private JLabel label_sport = new JLabel("目标端口:6000",JLabel.CENTER); private InetAddress cip = null;//本机ip private InetAddress sip = null;//对方ip private int otherport; private int myport; DatagramSocket socket;// 接收文件来显提示 DatagramSocket socket1;// 接收文件信息 DatagramSocket socket2;// 接收平时的聊天信息 // String filename = null; byte buffer[] = new byte[1024]; int fileLen = 0; int numofBlock = 0; int lastSize = 0; // String str_name; // public MyServer(String str_name, String str_ip, int otherport, int myport) { super(str_name); this.str_name = str_name; this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); this.setBounds(600, 250, 400, 500); // 添加功能代码 this.setLayout(new GridLayout(6, 1, 7, 7)); button_receive.setFont(new Font("楷体", 1, 20)); button_receive.setBackground(Color.LIGHT_GRAY); Font font = new Font("楷体",Font.PLAIN,20); label_cip.setFont(font); label_sip.setFont(font); label_cport.setFont(font); label_sport.setFont(font); label_fileState.setFont(font); //this.add(panel); this.add(label_cip); this.add(label_sip); this.add(label_cport); this.add(label_sport); this.add(button_receive); this.add(label_fileState); this.setVisible(true); // this.otherport = otherport; this.myport = myport; // button_receive.addActionListener(new ActionListener() {// 吧file1另存为file2 public void actionPerformed(ActionEvent e) { // 选择要接收的文件 JFileChooser filechooser = new JFileChooser(); int result = filechooser.showSaveDialog(MyServer.this); if (result == JFileChooser.APPROVE_OPTION) { try { File file2 = filechooser.getSelectedFile(); System.out.println("选择文件 "); try { File file1 = new File("D:\TT\" + filename); System.out.println(filename+"选择文件 "); saveAs(file1, file2); System.out.println("sava文件 "); } catch (Exception ex) { System.out.println(ex); } } catch (Exception ex) { JOptionPane.showMessageDialog(MyServer.this, "打开保存出错!"); } } } }); try{ this.cip=InetAddress.getLocalHost(); this.sip = InetAddress.getByName(str_ip); label_cip.setText("本机ip:"+this.cip.getHostAddress());//显示在面板上 label_sip.setText("目标ip:"+this.sip.getHostAddress());//显示在面板上 System.out.println(this.sip.getHostAddress()); socket = new DatagramSocket(this.myport); socket1 = new DatagramSocket(this.myport + 1); socket2 = new DatagramSocket(this.myport + 2); System.out.println("等待接受文件..."); while(true){ //接收文件名称 byte filetipBuf[] = new byte[256];// 防止文件名字过长(此处最长256个字符) DatagramPacket packet_tip = new DatagramPacket(filetipBuf, 0, filetipBuf.length); socket.receive(packet_tip); System.out.println(new String(packet_tip.getData())); String str_filetip = new String(packet_tip.getData(), 0,packet_tip.getLength()); filename = str_filetip.substring(8); //接收文件长度(字节数) byte[] fileLenBuf = new byte[12];// 可以传输1T的文件 DatagramPacket packet_len = new DatagramPacket(fileLenBuf,fileLenBuf.length); socket1.receive(packet_len); System.out.println(new String(packet_len.getData())); String str_fileLen = new String(fileLenBuf, 0,packet_len.getLength()); fileLen = Integer.parseInt(str_fileLen); label_fileState.setText("当前状态:正在接收!"); //接收文件内容 DatagramPacket packet_file = new DatagramPacket(buffer, 0,buffer.length); numofBlock = fileLen / buffer.length;// 循环次数(将该文件分成了多少块) lastSize = fileLen % buffer.length;// 最后一点点零头的字节数 File file = new File("D:\TT\" + filename); FileOutputStream fos = new FileOutputStream(file);// 从内存取出存入文件 for (int i = 0; i < numofBlock; i++) { packet_file = new DatagramPacket(buffer, 0,buffer.length); socket2.receive(packet_file);// 通过套接字接收数据 System.out.println(new String(packet_file.getData())); fos.write(buffer, 0, 1024);// 写入文件 } // 接收最后一点点零头 packet_file = new DatagramPacket(buffer, 0, lastSize); socket2.receive(packet_file);// 通过套接字接收数据 System.out.println(new String(packet_file.getData())); fos.write(buffer, 0, lastSize);// 写入文件 fos.close(); // 反馈包 label_fileState.setText("文件接收完毕!"); label_fileState.setText("当前状态:无任务"); // socket.close(); // socket1.close(); // socket2.close(); } }catch (Exception ex) { System.out.println("1"); } } public void saveAs(File file1, File file2) {// 把file1另存为file2,并删掉file1 try { FileInputStream fis = new FileInputStream(file1); FileOutputStream fos = new FileOutputStream(file2); byte buf[] = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { fos.write(buf, 0, len); } fis.close(); fos.close(); //file1.delete(); } catch (Exception ex) { System.out.println(ex); } } /////////////////////////////////////////////// public static void main(String args[]) { new MyServer("Server", "127.0.0.1", 6000, 10000); } }
本机环回地址测试通过,如有问题,请指正。