簡體   English   中英

通過TCP連接發送文件時丟失字節

[英]Missing bytes in sending files over TCP connection

通過TCP連接發送文件時缺少一些字節。 盡管有時文件傳輸已完成。

發送方:

class SendFile extends Thread {

Socket s;
String toIP;
String fileName;
PrintWriter pw;
BufferedReader br;
String fromIP;
String nextHopIP;
String transferTime;
int routingIndex;
final int bufferSize = 65536;
int readFile;
byte[] buffer;
FileInputStream fileIn;
OutputStream fileOut;
long fileTransferTime;

SendFile(String toIP, String fileName) {
    this.toIP = toIP;
    this.fileName = fileName;
}

public void run() {
    while (true) {
        try {
            fromIP = InetAddress.getLocalHost().getHostAddress();
            nextHopIP = Tables.checkRoutingTable(toIP);

            if (nextHopIP.equals("none")) {
                System.out.println("Invalid IP address");
            } else {
                s = new Socket(nextHopIP, 3434);

                fileIn = new FileInputStream(fileName);
                fileOut = s.getOutputStream();
                buffer = new byte[bufferSize];
                pw = new PrintWriter(s.getOutputStream());
                br = new BufferedReader(new InputStreamReader(s.getInputStream()));

                pw.println(fromIP);
                pw.println(toIP);
                pw.println(fileName.split("\\\\")[fileName.split("\\\\").length - 1]);
                pw.flush();

                //Send file
                fileTransferTime = System.currentTimeMillis();
                int sum = 0;
                while ((readFile = fileIn.read(buffer)) != -1) {
                    fileOut.write(buffer, 0, readFile);
                    sum += readFile;
                }
                System.out.println(sum);
                fileIn.close();
                s.shutdownOutput();
                br.readLine();
                fileTransferTime = System.currentTimeMillis() - fileTransferTime;
                System.out.println("File transfer time: " + fileTransferTime + " ms");
                s.close();
                break;
            }

        } catch (IOException ex) {
            //Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("Connection timed out. Retrying...");
        }
    }
}

}

接收方:

class FileTransferThread extends Thread {

Socket fromSocket;
Socket toSocket;
String ip;
BufferedReader fromBR;
BufferedReader toBR;
PrintWriter fromPW;
PrintWriter toPW;
String[][] delta;
String token;
String toIP;
String fromIP;
String nextHopIP;
String absoluteFileName;
String fileName;
int deltaCount;
int entryCount;
int socketIndex;
int i;
int j;
int readFile;
final int bufferSize = 65536;
byte[] buffer;
InputStream fileIn;
FileOutputStream fileOut;
OutputStream fileHopOut;
File directory;
long fileTransferTime;

FileTransferThread(Socket s) {
    this.fromSocket = s;
}

public void run() {
    try {
        ip = InetAddress.getLocalHost().getHostAddress();
        fromBR = new BufferedReader(new InputStreamReader(fromSocket.getInputStream()));
        fromPW = new PrintWriter(fromSocket.getOutputStream());
        fromIP = fromBR.readLine();
        toIP = fromBR.readLine();
        nextHopIP = Tables.checkRoutingTable(toIP);
        buffer = new byte[bufferSize];
        fileIn = fromSocket.getInputStream();
        fileName = fromBR.readLine();

        if (!fileName.equals("\\send")) {
            directory = new File("c:\\" + fromIP);
            directory.mkdirs();
            absoluteFileName = "c:\\" + fromIP + "\\" + fileName;
            fileOut = new FileOutputStream(absoluteFileName);

            while (true) {
                try {
                    //if not yet the destination IP, pass to next hop
                    if (!toIP.equals(ip)) {
                        toSocket = new Socket(toIP, 3434);
                        fileHopOut = toSocket.getOutputStream();
                        toBR = new BufferedReader(new InputStreamReader(toSocket.getInputStream()));
                        toPW = new PrintWriter(toSocket.getOutputStream());
                        toPW.println(fromIP);
                        toPW.println(toIP);
                        toPW.println(fileName);
                        toPW.flush();

                        //Send file
                        while ((readFile = fileIn.read(buffer)) != -1) {
                            fileHopOut.write(buffer, 0, readFile);
                        }
                        toSocket.shutdownOutput();
                        fromPW.println(toBR.readLine());
                        fromPW.flush();
                        toSocket.close();
                    } else {
                        int sum = 0;
                        while ((readFile = fileIn.read(buffer)) != -1) {
                            fileOut.write(buffer, 0, readFile);
                            sum += readFile;
                        }
                        System.out.println(sum);
                        fileOut.flush();
                        fileOut.close();
                        fromPW.println("1");
                        fromPW.flush();
                    }
                    fromSocket.close();
                    break;
                } catch (IOException ex) {
                    //Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex);
                    System.out.println("Connection timed out. Retrying...");
                }
            }
        } else {
            while(true) {
                try {
                    //if not yet the destination IP, pass to next hop
                    if (!toIP.equals(ip)) {
                        toSocket = new Socket(toIP, 3434);
                        fileHopOut = toSocket.getOutputStream();
                        toBR = new BufferedReader(new InputStreamReader(toSocket.getInputStream()));
                        toPW = new PrintWriter(toSocket.getOutputStream());
                        toPW.println(fromIP);
                        toPW.println(toIP);
                        toPW.println(fileName);
                        toPW.flush();
                        //Send file
                        while ((readFile = fileIn.read(buffer)) != -1) {
                            fileHopOut.write(buffer, 0, readFile);
                        }
                        toSocket.shutdownOutput();
                        fromPW.println(toBR.readLine());
                        fromPW.flush();
                        toSocket.close();
                    } else {
                        while ((readFile = fileIn.read(buffer)) != -1) {
                        }
                        fromPW.println("1");
                        fromPW.flush();
                    }
                    fromSocket.close();
                    break;
                }
                catch (IOException ex) {
                    //Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex);
                    System.out.println("Connection timed out. Retrying...");
                }
            }
        }
        fromSocket.close();
    } catch (IOException ex) {
        Logger.getLogger(FileTransferThread.class.getName()).log(Level.SEVERE, null, ex);
    }

}

}

您沒有關閉-因此也沒有刷新-名為fileout (您確實應該考慮減少誤導性的名稱...)。

嗯...看來shutdownOutput可以做到; 其javadoc寫道:

禁用此套接字的輸出流。 對於TCP套接字,將發送任何先前寫入的數據,然后是TCP的正常連接終止序列。

如果在套接字上調用shutdownOutput()后寫入套接字輸出流,則該流將拋出IOException。

萬一其他人有相同的想法,我就離開這個。

請注意, socket.getInputStream指定使用該工具可能發生的各種數據丟失。 尤其是:

網絡軟件可能會丟棄套接字緩沖的字節。

發現錯誤。 似乎BufferedReader正在獲取應該用於文件的數據塊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM