java网络编程:DatagramSocket类简单实现文件下载

来源:互联网 发布:js 跳转url 编辑:程序博客网 时间:2024/05/29 01:56

1、服务器端代码

import java.io.File;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  import java.io.IOException;  import java.io.InputStream;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.SocketException;  import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;    /**  * 下载服务器,采用UDP协议,传送的过程中可能会丢包,导致下载的文件不完整  */  public class DownloadServer {      // 提供服务      public void service() {          try {              // 创建本机指定端口8289的服务器              DatagramSocket dataSocket = new DatagramSocket(8289);              // 线程池,固定有十个线程              ExecutorService ThreadPool = Executors.newFixedThreadPool(10);                while (true) {// 不断接收来自客户端的请求                  byte[] buff = new byte[101];// 文件名长度不超过50                  DatagramPacket dataPacket = new DatagramPacket(buff, buff.length);                  dataSocket.receive(dataPacket);// 等待接收来自客户端的数据包                  // 接收到数据包,开一个线程为该客户服务                  ThreadPool.execute(new WorkThread(dataPacket));              }          } catch (SocketException e) {              e.printStackTrace();          } catch (IOException e) {              e.printStackTrace();          }      }        // 内部类,为每个客户提供服务      private class WorkThread implements Runnable {          private DatagramPacket packet;          private DatagramSocket dataSocket;            public WorkThread(DatagramPacket packet) {              this.packet = packet;              try {// 创建本机可以端口的DatagramSocket                  dataSocket = new DatagramSocket();              } catch (SocketException e) {                  e.printStackTrace();              }          }            // 获取可以下载的文件列表传送给客户端          private void showFiles() {              File files = new File("upload_download");              File[] allFile = files.listFiles();// 获取所有文件              StringBuffer message = new StringBuffer();              for (File f : allFile) {                  if (f.isFile()) {                      message.append(f.getName());                      message.append('\n');                  }              }              // 构造响应数据包              byte[] response = message.toString().getBytes();              DatagramPacket dataPacket = new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort());              try {// 发送                  dataSocket.send(dataPacket);              } catch (IOException e) {                  e.printStackTrace();              }          }            // 下载指定的文件          private void download(String fileName) {              try {                  InputStream in = new FileInputStream("upload_download/" + fileName);                  DatagramPacket dataPacket;                  byte[] response = new byte[60000];// 每次发送60000字节                  while (true) {                      int len = in.read(response, 0, response.length);                      dataPacket = new DatagramPacket(response, len, packet.getAddress(), packet.getPort());                      dataSocket.send(dataPacket);// 发送                      if (in.available() == 0)// 发送完毕                          break;                  }                  in.close();              } catch (FileNotFoundException e) {                  e.printStackTrace();              } catch (IOException e) {                  e.printStackTrace();              }          }            @Override          public void run() {              // 获取客户端传送过来的数据              byte[] data = packet.getData();              // 表示客户端点击显示文件按钮,该请求是要得到所有可以下载的文件              if (data[0] == 0)                  showFiles();              else if (data[0] == 1)// 表示客户端的请求是下载请求                  download(new String(data, 1, packet.getLength()).trim());              else                  System.out.println("请求错误");          }      }        public static void main(String[] args) {          new DownloadServer().service();      }  }  

说明:DatagramSocket 类是基于UDP协议,服务器端默认提供下载的文件存放在当前目录下的upload_download文件夹中。服务器采用线程池能同时为多个用户服务

2、客户端代码

import java.awt.BorderLayout;  import java.awt.GridLayout;  import java.awt.event.ActionEvent;  import java.awt.event.ActionListener;  import java.io.File;  import java.io.FileOutputStream;  import java.io.IOException;  import java.io.OutputStream;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetAddress;    import javax.swing.*;    /**  * 下载客户端  */  public class DownloadClient extends JFrame {      // 显示可下载的文件      private JTextArea textArea = new JTextArea();        private JPanel panel = new JPanel();      // 下载时保存文件      private JFileChooser saveFile = new JFileChooser(".");        private JButton showButton = new JButton("显示文件");      private JButton downloadButton = new JButton("下载...");      // 下载时填入要下载的文件名,注意文件名必须是textArea显示的文件名      private JTextField downloadFile = new JTextField("");        private DatagramSocket dataSocket=null;        public DownloadClient() {          // frame 的基本设置          this.setTitle("下载客户端");          this.setVisible(true);          this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);          this.setSize(400, 500);          this.setLayout(new BorderLayout());          this.setResizable(false);            // 设置不可编辑          textArea.setEditable(false);            panel.setLayout(new GridLayout(3, 2, 5, 5));          panel.add(new JLabel("点击按钮显示可下载的文件"));          panel.add(showButton);          panel.add(downloadFile);          panel.add(downloadButton);            // 组件加入frame中          add(new JScrollPane(textArea));          add(panel, BorderLayout.SOUTH);            // saveFile只能打开目录          saveFile.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);            // 显示文件按钮注册事件          showButton.addActionListener(new ActionListener() {              @Override              public void actionPerformed(ActionEvent e) {                  showButton.setEnabled(false);                  downloadButton.setEnabled(false);                  showFiles();                  showButton.setEnabled(true);                  downloadButton.setEnabled(true);              }          });            // 下载按钮注册事件          downloadButton.addActionListener(new ActionListener() {              @Override              public void actionPerformed(ActionEvent e) {                  showButton.setEnabled(false);                  downloadButton.setEnabled(false);                  downloadFile();                  showButton.setEnabled(true);                  downloadButton.setEnabled(true);              }          });      }        // 显示文件      private void showFiles() {          try {              if (dataSocket == null)                  dataSocket = new DatagramSocket();              // 创建发送数据包并发送给服务器              byte[] request = { 0 };              DatagramPacket requestPacket = new DatagramPacket(request, request.length, InetAddress.getLocalHost(), 8289);              dataSocket.send(requestPacket);                // 接收服务器的数据包,显示在textArea中              byte[] receive = new byte[1024 * 1024];              DatagramPacket receivePacket = new DatagramPacket(receive, receive.length);              dataSocket.receive(receivePacket);              String str = new String(receivePacket.getData(), 0, receivePacket.getLength());              textArea.setText(str);          } catch (IOException e) {              e.printStackTrace();          }      }        // 下载文件      private void downloadFile() {          // 获取要下载的文件名          String fileName = downloadFile.getText().trim();          // 所有可以下载的文件          String allFiles = textArea.getText();          // 文件名为空          if (fileName == null || "".equals(fileName))              JOptionPane.showMessageDialog(null, "请选中正确的文件名", "文件名错误", JOptionPane.WARNING_MESSAGE);          // 文件名是在可以下载的文件中          else if (allFiles.contains((fileName + '\n'))) {              saveFile.showSaveDialog(null);              File f = saveFile.getSelectedFile();// 获取选中的文件夹              if (f.exists()) {                  // 检测该文件是否已经存在于目录中                  String[] fileNames = f.list();                  boolean exit = false;                  for (String name : fileNames)                      if (name.equals(fileName)) {                          exit = true;                          break;                      }                    if (exit)// 如果要下载的文件已经存在                      JOptionPane.showMessageDialog(null, "此文件已经存在", "请选择另外的文件下载", JOptionPane.WARNING_MESSAGE);                  else {                      // 发送的请求                      byte[] request = (new String(new byte[] { 1 }) + fileName).getBytes();                      try {                          if (dataSocket == null)                              dataSocket = new DatagramSocket();                          // 创建发送数据包并发送给服务器                          DatagramPacket requestPacket = new DatagramPacket(request, request.length, InetAddress.getLocalHost(), 8289);                          dataSocket.send(requestPacket);                            // 接收服务器的数据包,把文件保存在选中的文件夹中                          OutputStream out = new FileOutputStream(f.getAbsolutePath() + "/" + fileName, true);                          byte[] receive = new byte[60000];// 每次接收60000字节                          DatagramPacket receivePacket;                          // 不断接收来自服务器的数据包                          while (true) {                              receivePacket = new DatagramPacket(receive, receive.length);                              dataSocket.receive(receivePacket);                              out.write(receivePacket.getData(), 0, receivePacket.getLength());// 输出流把文件内容输出到文件中                              out.flush();                              if (receivePacket.getLength() != receive.length)                                  break;                          }                          out.close();                      } catch (IOException e) {                          e.printStackTrace();                      }                  }                } else                  // 选择的文件夹不存在                  JOptionPane.showMessageDialog(null, "请选择正确的存储路径", "存储路径错误", JOptionPane.WARNING_MESSAGE);            } else {// 文件名错误              JOptionPane.showMessageDialog(null, "请选择正确的文件名", "文件名错误", JOptionPane.WARNING_MESSAGE);          }      }        public static void main(String[] args) {          new DownloadClient();      }  }  

说明:客户端下载时先点击显示文件,然后输入要下载的文件名,最后点击下载按钮、选择保存路径

3、运行时先开服务器,然后再开客户端。运行结果:

点击显示文件按钮、输入01.jpg后:

 

 

点击下载按钮后、选择保存路径

 

 

点击保存按钮后,文件下载到指定目录下

 


0 0
原创粉丝点击