本示例包括兩個客戶端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("選擇文件\n"); try { File file1 = new File("D:\\TT\\" + filename); System.out.println(filename+"選擇文件\n"); saveAs(file1, file2); System.out.println("sava文件\n"); } 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); } }
本機環回地址測試通過,如有問題,請指正。