歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java網絡編程六:DatagramSocket類簡單實現文件下載

Java網絡編程六:DatagramSocket類簡單實現文件下載

日期:2017/3/1 10:56:05   编辑:Linux編程

1、服務器端代碼

  1. package demo.net;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.net.DatagramPacket;
  8. import java.net.DatagramSocket;
  9. import java.net.SocketException;
  10. import java.util.concurrent.ExecutorService;
  11. import java.util.concurrent.Executors;
  12. /**
  13. * 下載服務器,采用UDP協議,傳送的過程中可能會丟包,導致下載的文件不完整
  14. */
  15. public class DownloadServer {
  16. // 提供服務
  17. public void service() {
  18. try {
  19. // 創建本機指定端口8289的服務器
  20. DatagramSocket dataSocket = new DatagramSocket(8289);
  21. // 線程池,固定有十個線程
  22. ExecutorService ThreadPool = Executors.newFixedThreadPool(10);
  23. while (true) {// 不斷接收來自客戶端的請求
  24. byte[] buff = new byte[101];// 文件名長度不超過50
  25. DatagramPacket dataPacket = new DatagramPacket(buff, buff.length);
  26. dataSocket.receive(dataPacket);// 等待接收來自客戶端的數據包
  27. // 接收到數據包,開一個線程為該客戶服務
  28. ThreadPool.execute(new WorkThread(dataPacket));
  29. }
  30. } catch (SocketException e) {
  31. e.printStackTrace();
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. // 內部類,為每個客戶提供服務
  37. private class WorkThread implements Runnable {
  38. private DatagramPacket packet;
  39. private DatagramSocket dataSocket;
  40. public WorkThread(DatagramPacket packet) {
  41. this.packet = packet;
  42. try {// 創建本機可以端口的DatagramSocket
  43. dataSocket = new DatagramSocket();
  44. } catch (SocketException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. // 獲取可以下載的文件列表傳送給客戶端
  49. private void showFiles() {
  50. File files = new File("upload_download");
  51. File[] allFile = files.listFiles();// 獲取所有文件
  52. StringBuffer message = new StringBuffer();
  53. for (File f : allFile) {
  54. if (f.isFile()) {
  55. message.append(f.getName());
  56. message.append('\n');
  57. }
  58. }
  59. // 構造響應數據包
  60. byte[] response = message.toString().getBytes();
  61. DatagramPacket dataPacket = new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort());
  62. try {// 發送
  63. dataSocket.send(dataPacket);
  64. } catch (IOException e) {
  65. e.printStackTrace();
  66. }
  67. }
  68. // 下載指定的文件
  69. private void download(String fileName) {
  70. try {
  71. InputStream in = new FileInputStream("upload_download/" + fileName);
  72. DatagramPacket dataPacket;
  73. byte[] response = new byte[60000];// 每次發送60000字節
  74. while (true) {
  75. int len = in.read(response, 0, response.length);
  76. dataPacket = new DatagramPacket(response, len, packet.getAddress(), packet.getPort());
  77. dataSocket.send(dataPacket);// 發送
  78. if (in.available() == 0)// 發送完畢
  79. break;
  80. }
  81. in.close();
  82. } catch (FileNotFoundException e) {
  83. e.printStackTrace();
  84. } catch (IOException e) {
  85. e.printStackTrace();
  86. }
  87. }
  88. @Override
  89. public void run() {
  90. // 獲取客戶端傳送過來的數據
  91. byte[] data = packet.getData();
  92. // 表示客戶端點擊顯示文件按鈕,該請求是要得到所有可以下載的文件
  93. if (data[0] == 0)
  94. showFiles();
  95. else if (data[0] == 1)// 表示客戶端的請求是下載請求
  96. download(new String(data, 1, packet.getLength()).trim());
  97. else
  98. System.out.println("請求錯誤");
  99. }
  100. }
  101. public static void main(String[] args) {
  102. new DownloadServer().service();
  103. }
  104. }

說明:DatagramSocket 類是基於UDP協議,服務器端默認提供下載的文件存放在當前目錄下的upload_download文件夾中。服務器采用線程池能同時為多個用戶服務


2、客戶端代碼

  1. package demo.net;
  2. import java.awt.BorderLayout;
  3. import java.awt.GridLayout;
  4. import java.awt.event.ActionEvent;
  5. import java.awt.event.ActionListener;
  6. import java.io.File;
  7. import java.io.FileOutputStream;
  8. import java.io.IOException;
  9. import java.io.OutputStream;
  10. import java.net.DatagramPacket;
  11. import java.net.DatagramSocket;
  12. import java.net.InetAddress;
  13. import javax.swing.*;
  14. /**
  15. * 下載客戶端
  16. */
  17. public class DownloadClient extends JFrame {
  18. // 顯示可下載的文件
  19. private JTextArea textArea = new JTextArea();
  20. private JPanel panel = new JPanel();
  21. // 下載時保存文件
  22. private JFileChooser saveFile = new JFileChooser(".");
  23. private JButton showButton = new JButton("顯示文件");
  24. private JButton downloadButton = new JButton("下載...");
  25. // 下載時填入要下載的文件名,注意文件名必須是textArea顯示的文件名
  26. private JTextField downloadFile = new JTextField("");
  27. private DatagramSocket dataSocket=null;
  28. public DownloadClient() {
  29. // frame 的基本設置
  30. this.setTitle("下載客戶端");
  31. this.setVisible(true);
  32. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  33. this.setSize(400, 500);
  34. this.setLayout(new BorderLayout());
  35. this.setResizable(false);
  36. // 設置不可編輯
  37. textArea.setEditable(false);
  38. panel.setLayout(new GridLayout(3, 2, 5, 5));
  39. panel.add(new JLabel("點擊按鈕顯示可下載的文件"));
  40. panel.add(showButton);
  41. panel.add(downloadFile);
  42. panel.add(downloadButton);
  43. // 組件加入frame中
  44. add(new JScrollPane(textArea));
  45. add(panel, BorderLayout.SOUTH);
  46. // saveFile只能打開目錄
  47. saveFile.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
  48. // 顯示文件按鈕注冊事件
  49. showButton.addActionListener(new ActionListener() {
  50. @Override
  51. public void actionPerformed(ActionEvent e) {
  52. showButton.setEnabled(false);
  53. downloadButton.setEnabled(false);
  54. showFiles();
  55. showButton.setEnabled(true);
  56. downloadButton.setEnabled(true);
  57. }
  58. });
  59. // 下載按鈕注冊事件
  60. downloadButton.addActionListener(new ActionListener() {
  61. @Override
  62. public void actionPerformed(ActionEvent e) {
  63. showButton.setEnabled(false);
  64. downloadButton.setEnabled(false);
  65. downloadFile();
  66. showButton.setEnabled(true);
  67. downloadButton.setEnabled(true);
  68. }
  69. });
  70. }
  71. // 顯示文件
  72. private void showFiles() {
  73. try {
  74. if (dataSocket == null)
  75. dataSocket = new DatagramSocket();
  76. // 創建發送數據包並發送給服務器
  77. byte[] request = { 0 };
  78. DatagramPacket requestPacket = new DatagramPacket(request, request.length, InetAddress.getLocalHost(), 8289);
  79. dataSocket.send(requestPacket);
  80. // 接收服務器的數據包,顯���在textArea中
  81. byte[] receive = new byte[1024 * 1024];
  82. DatagramPacket receivePacket = new DatagramPacket(receive, receive.length);
  83. dataSocket.receive(receivePacket);
  84. String str = new String(receivePacket.getData(), 0, receivePacket.getLength());
  85. textArea.setText(str);
  86. } catch (IOException e) {
  87. e.printStackTrace();
  88. }
  89. }
  90. // 下載文件
  91. private void downloadFile() {
  92. // 獲取要下載的文件名
  93. String fileName = downloadFile.getText().trim();
  94. // 所有可以下載的文件
  95. String allFiles = textArea.getText();
  96. // 文件名為空
  97. if (fileName == null || "".equals(fileName))
  98. JOptionPane.showMessageDialog(null, "請選中正確的文件名", "文件名錯誤", JOptionPane.WARNING_MESSAGE);
  99. // 文件名是在可以下載的文件中
  100. else if (allFiles.contains((fileName + '\n'))) {
  101. saveFile.showSaveDialog(null);
  102. File f = saveFile.getSelectedFile();// 獲取選中的文件夾
  103. if (f.exists()) {
  104. // 檢測該文件是否已經存在於目錄中
  105. String[] fileNames = f.list();
  106. boolean exit = false;
  107. for (String name : fileNames)
  108. if (name.equals(fileName)) {
  109. exit = true;
  110. break;
  111. }
  112. if (exit)// 如果要下載的文件已經存在
  113. JOptionPane.showMessageDialog(null, "此文件已經存在", "請選擇另外的文件下載", JOptionPane.WARNING_MESSAGE);
  114. else {
  115. // 發送的請求
  116. byte[] request = (new String(new byte[] { 1 }) + fileName).getBytes();
  117. try {
  118. if (dataSocket == null)
  119. dataSocket = new DatagramSocket();
  120. // 創建發送數據包並發送給服務器
  121. DatagramPacket requestPacket = new DatagramPacket(request, request.length, InetAddress.getLocalHost(), 8289);
  122. dataSocket.send(requestPacket);
  123. // 接收服務器的數據包,把文件保存在選中的文件夾中
  124. OutputStream out = new FileOutputStream(f.getAbsolutePath() + "/" + fileName, true);
  125. byte[] receive = new byte[60000];// 每次接收60000字節
  126. DatagramPacket receivePacket;
  127. // 不斷接收來自服務器的數據包
  128. while (true) {
  129. receivePacket = new DatagramPacket(receive, receive.length);
  130. dataSocket.receive(receivePacket);
  131. out.write(receivePacket.getData(), 0, receivePacket.getLength());// 輸出流把文件內容輸出到文件中
  132. out.flush();
  133. if (receivePacket.getLength() != receive.length)
  134. break;
  135. }
  136. out.close();
  137. } catch (IOException e) {
  138. e.printStackTrace();
  139. }
  140. }
  141. } else
  142. // 選擇的文件夾不存在
  143. JOptionPane.showMessageDialog(null, "請選擇正確的存儲路徑", "存儲路徑錯誤", JOptionPane.WARNING_MESSAGE);
  144. } else {// 文件名錯誤
  145. JOptionPane.showMessageDialog(null, "請選擇正確的文件名", "文件名錯誤", JOptionPane.WARNING_MESSAGE);
  146. }
  147. }
  148. public static void main(String[] args) {
  149. new DownloadClient();
  150. }
  151. }

說明:客戶端下載時先點擊顯示文件,然後輸入要下載的文件名,最後點擊下載按鈕、選擇保存路徑

3、運行時先開服務器,然後再開客戶端。運行結果:

點擊顯示文件按鈕、輸入01.jpg後:

點擊下載按鈕後、選擇保存路徑

點擊保存按鈕後,文件下載到指定目錄下

Copyright © Linux教程網 All Rights Reserved