通过TCP连接发送文件时缺少字节

时间:2010-09-01 21:44:18

标签: java sockets tcp

当我通过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);
    }

}

}

3 个答案:

答案 0 :(得分:1)

你没有关闭 - 因此没有刷新 - 名为fileout的SocketOutputStream。 (你真的应该考虑减少误导性的名字......)。

嗯...看来shutdownOutput会这样做;它的javadoc写道:

  

禁用此套接字的输出流。   对于TCP套接字,将发送任何以前写入的数据   然后是TCP的正常连接终止序列。

     

如果在调用后写入套接字输出流   socket上的shutdownOutput(),流将抛出   IOException。

我留下这个以防其他人有同样的想法。

答案 1 :(得分:0)

请注意socket.getInputStream指定使用该工具可能发生的各种数据丢失。特别是:

  

网络软件可能会丢弃字节   由套接字缓冲。

答案 2 :(得分:0)

发现错误。似乎BufferedReader正在获取应该用于文件的一大块数据。