前一篇文章是基于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();
}
}