UDP文件传输程序

      前一篇文章是基于TCP的,好不容易做完后老师又让弄个UDP的......

      目前可以连通了,但是传输上丢失文件情况相当严重。

这是服务器,先选择文件,连通后等待服务器读取

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.JFileChooser;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;

public class UDPServer extends JFrame {
  private String file_path; //文件夹路径
  private int server_port; //服务器端口
  private int file_port; //文件传输端口
  private DatagramSocket server;
  private DatagramSocket file_server;
  private boolean flag = true; //控制服务是否启动
  private JTable table = new JTable();
  private Vector row = new Vector();
  private Vector head = new Vector();
  private JFrame table_frame = new JFrame();
  private JScrollPane pane;
  private DefaultTableModel tableModel = new DefaultTableModel();
  private ProgressCellModel cellModel = new ProgressCellModel();
  private javax.swing.JLabel msg_lb;
  private javax.swing.JLabel path_lb;
  private javax.swing.JTextField path_tf;
  private javax.swing.JLabel port_lb;
  private javax.swing.JTextField port_tf;
  private javax.swing.JButton select_dir;
  private javax.swing.JButton start_server;
  private javax.swing.JButton stop_server;
  private UDPServer udp_server;

  public UDPServer(String file_path, int server_port) {
  this.file_path = file_path;
  this.server_port = server_port;
  this.file_port = 3001;
  addTableHead();
  }
  /**
  * 这是给table加个表头用的
  */
  private void addTableHead() {
  head.add("IP");
  head.add("文件名");
  head.add("大小");
  head.add("进度");
  head.add("百分比");
  head.add("状态");
  pane = new JScrollPane(table);
  }

  public UDPServer() {
  addTableHead();

  JFrame frame = new JFrame();
  JPanel panel = new JPanel();
  frame.setSize(300, 150);
  select_dir = new JButton("选择文件夹");
  msg_lb = new JLabel("服务已停止");
  path_lb = new JLabel("路径");
  port_lb = new JLabel("端口");
  path_tf = new JTextField(20);
  path_tf.setEditable(false);
  port_tf = new JTextField(20);
  start_server = new JButton("启动服务");
  stop_server = new JButton("停止服务");
  select_dir.setText("选择文件夹");
  //给按钮添加事件,选择客户端可下载的文件所在的文件夹
  select_dir.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
  JFileChooser chooser = new JFileChooser();
  chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
  int value = chooser.showOpenDialog(null);
  if (value == JFileChooser.APPROVE_OPTION) {
  path_tf.setText(chooser.getSelectedFile().getPath());
  }
  }
  });

  start_server.addActionListener(new ActionListener() {
  //启动服务事件
  public void actionPerformed(java.awt.event.ActionEvent evt) {
  int listen_port = 3000;
  if (!port_tf.getText().trim().equals("")) {
  listen_port = Integer.parseInt(port_tf.getText().trim());
  }
  udp_server = new UDPServer(path_tf.getText(), listen_port);
  udp_server.startServer();
  msg_lb.setText("服务已启动");
  }
  });

  stop_server.addActionListener(new ActionListener() {
  public void actionPerformed(java.awt.event.ActionEvent evt) {
  udp_server.stopServer();
  msg_lb.setText("服务已关闭");
  }
  });

  panel.add(path_lb);
  panel.add(path_tf);
  panel.add(select_dir);
  panel.add(start_server);
  panel.add(stop_server);
  panel.add(msg_lb);
  frame.add(panel);
  frame.setResizable(false);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
  }
  /**
  * 自定义滚动条
  */
  public class MyProgressBar
  extends JProgressBar
  implements TableCellRenderer {public MyProgressBar(int min, int max) {
  super(min, max);
  this.setBackground(Color.white);
  this.setForeground(Color.CYAN);
  }

  public Component getTableCellRendererComponent(
  JTable table,
  Object value,
  boolean isSelected,
  boolean hasFocus,
  int row,
  int column) {
  setValue(Integer.parseInt(String.valueOf(value)));
  return this;
  }
  }

  public class ProgressCellModel extends DefaultTableCellRenderer {
  public Component getTableCellRendererComponent(
  JTable table,
  Object value,
  boolean isSelected,
  boolean hasFocus,
  int row,
  int column) {
  Component cell =
  super.getTableCellRendererComponent(
  table,
  value,
  isSelected,
  hasFocus,
  row,
  column);
  TableColumn tableColumn = table.getColumnModel().getColumn(column);
  String strColumnHeader = String.valueOf(tableColumn.getHeaderValue());
  if (strColumnHeader.equals("进度")) {
  MyProgressBar progressbar =
  new MyProgressBar(0, 100);
  tableColumn.setCellRenderer(progressbar);
  }
  return cell;
  }
  }
   
  void startServer() {
  //创建ServerSocket
  try {
  if (server == null) {
  server = new DatagramSocket(server_port);
  }
  if (file_server == null) {
  file_server = new DatagramSocket(file_port);
  }
  //启动了一个线程,来等待客户端的链接
  new ConnThread().start();
  new FileThread().start();
  } catch (IOException e) {
  e.printStackTrace();
  }
  }

  private class ConnThread extends Thread {
  public void run() {
  while (flag) {
  try {
  byte buffer[] = new byte[256];
  DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
  server.receive(packet);
  putFileList(packet);
  } catch (IOException e) {
  e.printStackTrace();
  }
  }
  }
  }

  //把文件夹里的文件列表传给客户端
  private void putFileList(DatagramPacket packet) {
  //取得连接的地址和端口
  InetAddress address = packet.getAddress();
  int port = packet.getPort();
  File file = new File(file_path);
  String[] file_names = file.list();
  String s = "";
  for (String str : file_names) {
  s = s + str + ";";
  }
  byte[] b = s.getBytes();
  packet = new DatagramPacket(b, b.length, address, port);
  try {
  server.send(packet);
  } catch (IOException ex) {
  ex.printStackTrace();
  }
  }
   
  private class FileThread extends Thread {
  public void run() {
  while (flag) {
  try {
  byte buffer[] = new byte[256];
  DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
  file_server.receive(packet);
  //这里启动一个线程,等待客户端获取文件
  new SendThread(packet).start();
  new TableThread().start();
  } catch (IOException e) {
  e.printStackTrace();
  }
  }
  }
  }
  //线程类,等待客户机下载文件
  private class SendThread extends Thread {
  private DatagramPacket packet;
  public SendThread(DatagramPacket packet) {
  this.packet = packet;
  }
  public void run() {
  download(packet);
  }
  }

  private void download(DatagramPacket packet) {
  try {
  String file_str = new String(packet.getData(), 0, packet.getLength());
  File file = new File(file_path, file_str);
  FileInputStream filein = new FileInputStream(file);
  byte[] b = new byte[1024];
  long i = 0; //已传输的字节数
  String l = ""; //已K来计算已传输的数量
  String per = ""; //显示百分比
  int length = 0;
  table_frame.setSize(400, 400);
  table_frame.add(pane);
  Vector cell = new Vector();
  cell.add(packet.getAddress());
  cell.add(file_str);
  cell.add(l);
  cell.add(per);
  cell.add("传输中...");
  row.add(cell);
  tableModel.setDataVector(row, head);
  table.setModel(tableModel);
  table.setDefaultRenderer(
  Class.forName("java.lang.Object"),
  cellModel);
  table_frame.setVisible(true);
  //取得连接的地址和端口
  InetAddress address = packet.getAddress();
  int port = packet.getPort();
  while ((length = filein.read(b)) != -1) {
  packet = new DatagramPacket(b, length, address, port);
  try {
  file_server.send(packet);
  } catch (IOException ex) {
  Logger.getLogger(UDPServer.class.getName()).log(Level.SEVERE, null, ex);
  }
  i = i + length;
  l = i / 1024 + "K";
  per = (i * 100 / file.length()) + "%";
  cell.set(2, l);
  cell.set(3, (int) (i * 100 / file.length()));
  cell.set(4, per);
  cell.set(5, "传输中...");
  }
  filein.close();
  cell.set(5, "传输完毕");
  } catch (Exception e) {
  System.out.println("Error handling a client: " + e);
  }
  }
  //线程,刷新table
  private class TableThread extends Thread {
  public void run() {
  while (true) {
  table.repaint();
  }
  }
  }
  public void stopServer() {
  flag = false;
  }
  public static void main(String[] args) {
  UDPServer server = new UDPServer();
  }
}
*************************************************************************************************************

下面是客户端,默认是本地传输地址。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Vector;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

public class UDPClient extends JFrame {
  private String host_ip; //主机ip
  private int host_port; //主机端口
  private int file_port = 3001; //文件传输端口
  private DatagramSocket client_socket;
  private DatagramPacket packet;
  private String selected; //选中的文件名
  private JLabel ip_lb, port_lb;
  private JTextField ip_tf, port_tf;
  private JButton link_bt;
  private UDPClient client;
  //构造方法
  public UDPClient(String host_ip, int host_port) {
  System.out.println(host_ip + "," + host_port);
  this.host_ip = host_ip;
  this.host_port = host_port;
  }
   
  public UDPClient() {
  setSize(350, 200);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel panel = new JPanel();
  JFrame frame = new JFrame();
  ip_lb = new JLabel("IP");
  port_lb = new JLabel("端口");
  ip_tf = new JTextField(20);
  port_tf = new JTextField(20);
  link_bt = new JButton("连接");
  ip_tf = new JTextField("127.0.0.1");
  port_tf = new JTextField("3000");
  //读取服务器的文件列表
  link_bt.addActionListener(new ActionListener() {

  public void actionPerformed(ActionEvent e) {
  String ip = ip_tf.getText().trim();
  int port = Integer.parseInt(port_tf.getText().trim());
  client = new UDPClient(ip, port);
  client.connect();
  }
  });
  //创建窗口
  panel.add(ip_lb);
  panel.add(ip_tf);
  panel.add(port_lb);
  panel.add(port_tf);
  panel.add(link_bt);
  frame.add(panel);
  frame.setResizable(false);
  frame.setSize(270, 120);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
  }
  //连接到服务器端
  public void connect() {
  try {
  client_socket = new DatagramSocket();
  byte[] b = new byte[1024];
  packet = new DatagramPacket(b, b.length, 
  InetAddress.getByName(host_ip), host_port);
  client_socket.send(packet);
  packet = new DatagramPacket(b, b.length);
  client_socket.receive(packet);
  String files = new String(packet.getData(), 0, packet.getLength());
  if (!files.trim().equals("")) {
  showFileList(files);
  }
  client_socket.close();
  } catch (UnknownHostException e) {
  System.out.println("Error setting up socket connection: unknown host at " + host_ip + ":" + host_port);
  } catch (IOException e) {
  System.out.println("Error setting up socket connection: " + e);
  }
  }
  //创建一个文件列表的窗口
  private void showFileList(String files) {
  JFrame frame = new JFrame();
  frame.setSize(400, 400);
  JTable table = new JTable();
  createTable(table, files);
  JScrollPane pane = new JScrollPane(table);
  frame.add(pane);
  JButton get_file = new JButton("传输文件");
  //按钮事件,下载文件用的
  get_file.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
  //启动一个下载线程,以免阻塞主线程
  new DownFile().start();
  }
  });
  frame.add(get_file, BorderLayout.SOUTH);
  frame.setVisible(true);
  }
  //创建文件列表
  private void createTable(JTable table, String files) {
  DefaultTableModel tableModel = new DefaultTableModel();
  final Vector row = new Vector();
  Vector cell;
  String[] f = files.split(";");
  for (String str : f) {
  cell = new Vector();
  cell.add(str);
  row.add(cell);
  }
  Vector head = new Vector();
  head.add("文件");
  tableModel.setDataVector(row, head);
  table.setModel(tableModel);
  ListSelectionModel model = table.getSelectionModel();
  model.addListSelectionListener(new ListSelectionListener() {
  public void valueChanged(ListSelectionEvent e) {
  if (e.getValueIsAdjusting()) {
  int index = ((DefaultListSelectionModel) (e.getSource())).getAnchorSelectionIndex();
  selected = (String) ((Vector) row.get(index)).get(0);
  }
  }
  });
  }
  /**
  * 下载文件,一个文件一个线程
  */
  private class DownFile extends Thread {

  public void run() {
  JFileChooser chooser = new JFileChooser();
  //设置默认保存的文件名
  chooser.setSelectedFile(new File(".", selected));
  int value = chooser.showSaveDialog(null);
  if (value == JFileChooser.APPROVE_OPTION) {
  try {
  byte[] temp = selected.getBytes();
  DatagramPacket packet = new DatagramPacket(temp, temp.length, 
  InetAddress.getByName("localhost"), 3001);
  client_socket = new DatagramSocket();
  client_socket.send(packet);
  //取得选取的文件
  File file = chooser.getSelectedFile();
  //准备写入
  FileOutputStream fileout = new FileOutputStream(file);
  //取得服务器端的流
  //下面为传输
  byte[] b = new byte[1024];
  int i = 0;
  packet = new DatagramPacket(b, b.length);
  do {
  client_socket.receive(packet);
  fileout.write(b, 0, packet.getLength());
  fileout.flush();
  } while (packet.getLength() != 0);
  //关闭流
  client_socket.close();
  fileout.close();
  } catch (IOException e1) {
  e1.printStackTrace();
  }
  }
  }
  }
  public static void main(String[] arguments) {
  UDPClient frame = new UDPClient();
  }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值