java实现TCP与UDP混合传输文件总结

java实现TCP与UDP混合传输文件总结


    最近在用java写基于UDP传输文件的网络,遇到了很多问题,也参考了很多人编写的程序,通过 自己的整理和设计,终于写完了自己程序,现在将在编程中遇到的问题总结一下。

发送方:
    首先发送方需要发送文件的一些属性给文件接收方,如文件的名称,文件的大小等,让文件接收方判断是否接受文件,由于这部分内容比较重要,不能出现丢包的现象,所以采用TCP/IP协议来传输文件,而在文件传输的时候,我们采用UDP协议传输,这样能让文件传输得更快。先看一下发送方代码。

import java.awt.*;
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import java.util.concurrent.TimeUnit;
    import javax.swing.*;
    public class FileClient extends JFrame {
    FileDialog fd1 = null;
    DatagramSocket ds = null;
    DatagramPacket sendDp = null;
    static int sendDataLen = 10240;
    public byte[] sendBuff = new byte[sendDataLen];
    public InetAddress udpIP = null;
    static int udpPort = 10000;
    static int tcpPort = 9999;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        FileClient fc = new FileClient();
        fc.fileSender();

    }

    public void fileSender() {
        try {
            // 打开windows的文件对话框
            fd1 = new FileDialog(this, "请选择需要打开的文件", FileDialog.LOAD);
            fd1.setVisible(true);
            String filePath = fd1.getDirectory() + fd1.getFile();
            String location = filePath.replaceAll("\\\\", "/");
            System.out.println("绝对文件目录+文件名" + filePath);
            System.out.println("绝对文件目录+文件名" + location);
            DataInputStream dis = new DataInputStream(new BufferedInputStream(
                    new FileInputStream(location)));
            // 单位是字节
            int fileLen = dis.available();
            System.out.println("文件长度" + fileLen);
            // ****************************************************
            // 写一个TCP协议发送文件标题,让接受端确认是否接受
            Socket s = new Socket("127.0.0.1", tcpPort);// 发送到本机
            PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
            String headInfo = fd1.getFile() + "/" + fileLen;

            pw.println(headInfo);
            // 等待对方确认
            InputStreamReader isr = new InputStreamReader(s.getInputStream());
            BufferedReader br = new BufferedReader(isr);
            // 阻塞等待
            String info = br.readLine();
            System.out.println("我接收到文件接收器给我返回的内容了=" + info);
            if (info.equals("YES")) {
                s.close();
                System.out.println("我是文件发送器UDP,我已经开始发送了");
                // 主机从任意空闲端口发送;
                ds = new DatagramSocket();
                udpIP = InetAddress.getByName("127.0.0.1");
                while (dis.read(sendBuff) > 0) {
                    sendDp = new DatagramPacket(sendBuff, sendBuff.length,
                            udpIP, udpPort);
                    ds.send(sendDp);
                    TimeUnit.MICROSECONDS.sleep(1);// 限制传输速度
                    // ******************************************
                }
            } else {
                JOptionPane.showMessageDialog(null, "对方拒绝接受文件", "消息提示",
                        JOptionPane.WARNING_MESSAGE);
                dis.close();
                s.close();
            }
            System.out.println("发送完毕");
            dis.close();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }

    }
    }

接收方(有一个确认接对话框类):

package com.tcpip.model;

    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.*;
    import java.net.*;
    import javax.swing.*;       
    public class FileReceiver {
    static final int receivePort = 10000;
    DatagramPacket receiveDp = null;
    DatagramSocket receiveDs = null;
    int dataLen = 10240;
    public byte[] inBuff = new byte[dataLen];
    String filePath = null;
    InetAddress clientIp = null;
    String myUserId = "小富";

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        FileReceiver fr = new FileReceiver();
        fr.fileReceiver();
    }

    public void fileReceiver() {
        try {
            // 写一个TCP接收协议,判断是否接受对方发过来的信息
            ServerSocket ss = new ServerSocket(9999);
            // 阻塞,等待接收
            Socket s = ss.accept();
            PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
            // 读取客户端信息
            InputStreamReader isr = new InputStreamReader(s.getInputStream());
            BufferedReader br = new BufferedReader(isr);
            // 阻塞,等待接收从缓存中读取
            String fileInfo = br.readLine();
            String headInfomation[] = fileInfo.split("/");
            String fileName = headInfomation[0];
            String fileLen0 = headInfomation[1];
            System.out.println("tcp接受到的内容为=" + headInfomation[0]);
            System.out.println("tcp接受到的内容为=" + headInfomation[1]);
            int fileLen = Integer.parseInt(fileLen0);
            // 显示面板,显示对方发过来的文件信息,文件名称及文件大小,并确定是否收文件
            ReceiveConfirm rc = new ReceiveConfirm(myUserId, fileName, fileLen);
            String wait = rc.getLocationpath();
            // 等待存储文件的路径的产生
            while (wait.equals("wait")) {
                wait = rc.getLocationpath();
                System.out.println("我在这儿等待接收存储方的文件目录");
            }
            String headInfo = "YES";
            pw.println(headInfo);
            ss.close();
            String filePath = rc.getLocationpath();
            System.out.println("保存文件到目录" + fileInfo);
            DataOutputStream fileOut = new DataOutputStream(
                    new BufferedOutputStream(new FileOutputStream(filePath)));
            receiveDs = new DatagramSocket(receivePort);
            System.out.println("我是文件接收器1,我已经运行");
            int times = fileLen / dataLen;// 循环接收的次数
            int restSize = fileLen % dataLen;// 接收剩下的字节
            for (int i = 0; i < times; i++) {
                System.out.println("服务器已启动");
                receiveDp = new DatagramPacket(inBuff, inBuff.length);
                receiveDs.receive(receiveDp);
                fileOut.write(inBuff, 0, receiveDp.getLength());
                fileOut.flush();
            }
            // 接收最后剩下,在inBuffer中能存下。
            if (restSize != 0) {
                System.out.println("我有剩余");
                receiveDp = new DatagramPacket(inBuff, inBuff.length);
                receiveDs.receive(receiveDp);
                fileOut.write(inBuff, 0, receiveDp.getLength());
                fileOut.flush();
                fileOut.close();
            }
            System.out.println("接收完毕" + fileLen);
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            if (receiveDs != null) {
                // 关闭receiveDs的对象
                receiveDs.close();
            }
            JOptionPane.showMessageDialog(null,
                    "发送信息异常,请确认10000(接收端)号端口空闲,且网络连接正常", "网络异常",
                    JOptionPane.ERROR_MESSAGE);
            System.exit(1);
        }
    }
    }

    class ReceiveConfirm implements ActionListener {
    // dingyi
    JLabel jl;
    JButton jb1, jb2;
    JPanel jp1, jp2;
    String headInfo = null;
    String myUserId = null;
    int fileLen = 0;
    float result = 0f;
    JFrame jf = null;
    private static String locationpath = "wait";

    public ReceiveConfirm(String myUserId, String headInfo, int fileLen) {
        jf = new JFrame();
        this.headInfo = headInfo;
        this.myUserId = myUserId;
        this.fileLen = fileLen;
        result = fileLen / 1024;
        System.out.println(myUserId + headInfo);
        // 创建
        jl = new JLabel(myUserId + " 发来文件:【 " + headInfo + " 】,文件大小" + result
                + "KB,是否接受");
        jb1 = new JButton("是");
        jb1.addActionListener(this);
        jb2 = new JButton("否");
        jb2.addActionListener(this);
        jp1 = new JPanel();
        jp2 = new JPanel();
        // 布局管理设置
        // 添加组件
        jp1.add(jl);
        jp2.add(jb1);
        jp2.add(jb2);
        jf.add(jp1, "Center");
        jf.add(jp2, "South");
        // 设置属性
        jf.setSize(500, 120);
        jf.setTitle("提示信息");
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);
        jf.setLocation(550, 300);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        if (e.getSource() == jb1) {
            jf.dispose();
            // FileDialogTest fdt=new FileDialogTest();
            JFrame jf = new JFrame();
            FileDialog fd = new FileDialog(jf, "选择保存文件路径", FileDialog.SAVE);
            fd.setVisible(true);
            System.out.println("保存位置" + fd.getDirectory() + fd.getFile());
            String filePath = fd.getDirectory() + fd.getFile();
            locationpath = filePath.replaceAll("\\\\", "/");
            System.out.println("保存位置1" + locationpath);
        }
    }

    public String getLocationpath() {
        System.out.println("保存位置2" + locationpath);
        return locationpath;
    }
    }

猜你喜欢

转载自fjding.iteye.com/blog/2311246
今日推荐