java實現TCP與UDP混合傳輸檔案總結

小鞅發表於2015-04-07

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;
    }
    }
<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>

相關文章