本示例包括两个客户端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);
}
}
本机环回地址测试通过,如有问题,请指正。