zoukankan      html  css  js  c++  java
  • java实现PC之间的udp数据单向传输

    本示例包括两个客户端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("选择文件
    ");
    try {
    File file1 = new File("D:\TT\" + filename);
    System.out.println(filename+"选择文件
    ");
    saveAs(file1, file2);
    System.out.println("sava文件
    ");
    } 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);
    }
    }
    

      

    本机环回地址测试通过,如有问题,请指正。

  • 相关阅读:
    一只特立独行的猪
    每天写出好代码的5个建议
    电脑修好了
    VB编程修改AutoCAD长度型尺寸标注
    前天我放学回家
    VB编程修改AutoCAD坐标型尺寸标注
    VB编程操作AutoCAD尺寸标注样式
    这是一个错误的程序
    2011年6月27日星期二
    2011年6月20日星期一
  • 原文地址:https://www.cnblogs.com/catherinezyr/p/6490722.html
Copyright © 2011-2022 走看看