使用Java套接字发送文件,丢失数据

0x5*_*453 2 java sockets tcp file-transfer

我正在尝试将文件从客户端发送到带有Java套接字的服务器.当我在同一台机器上测试时它工作正常,但是当我在不同的机器上测试时,我丢失了大量数据,导致文件损坏.如果我尝试发送一个非常小的文件(<20字节),它甚至不会到达服务器的while循环中的println.

这是我的代码:

Server.java

package edu.mst.cs.sensorreceiver;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    private static final int PORT = 51111;
    private static final int CHUNK_SIZE = 1024;
    private static final File _downloadDir = new File("downloads/");

    public static void main(String[] args) {
        if (!_downloadDir.exists()) {
            if (!_downloadDir.mkdirs()) {
                System.err.println("Error: Could not create download directory");
            }
        }

        Socket socket = null;
        try {
            ServerSocket server = new ServerSocket(PORT);

            while (true) {
                System.out.println("Waiting for connection...");
                socket = server.accept();

                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                String name = in.readLine();
                File file = new File(_downloadDir, name);

                String size = in.readLine();
                int fileSize;
                try {
                    fileSize = Integer.parseInt(size);
                } catch (NumberFormatException e) {
                    System.err.println("Error: Malformed file size:" + size);
                    e.printStackTrace();
                    return;
                }

                System.out.println("Saving " + file + " from user... (" + fileSize + " bytes)");
                saveFile(file, socket.getInputStream());
                System.out.println("Finished downloading " + file + " from user.");
                if (file.length() != fileSize) {
                    System.err.println("Error: file incomplete");
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void saveFile(File file, InputStream inStream) {
        FileOutputStream fileOut = null;
        try {
            fileOut = new FileOutputStream(file);

            byte[] buffer = new byte[CHUNK_SIZE];
            int bytesRead;
            int pos = 0;
            while ((bytesRead = inStream.read(buffer, 0, CHUNK_SIZE)) >= 0) {
                pos += bytesRead;
                System.out.println(pos + " bytes (" + bytesRead + " bytes read)");
                fileOut.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOut != null) {
                try {
                    fileOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("Finished, filesize = " + file.length());
    }
}
Run Code Online (Sandbox Code Playgroud)

Client.java

package edu.mst.cs.sensorreceiver;

import java.io.*;
import java.net.Socket;

public class Client {
    private static final String HOSTNAME = "131.151.163.153";
    private static final int PORT = 51111;
    private static final int CHUNK_SIZE = 1024;

    public static void main(String[] args) {
        sendFile(args[0]);
    }

    private static void sendFile(String path) {
        if (path == null) {
            throw new NullPointerException("Path is null");
        }

        File file = new File(path);
        Socket socket = null;
        try {
            System.out.println("Connecting to server...");
            socket = new Socket(HOSTNAME, PORT);
            System.out.println("Connected to server at " + socket.getInetAddress());

            PrintStream out = new PrintStream(socket.getOutputStream(), true);

            out.println(file.getName());
            out.println(file.length());

            System.out.println("Sending " + file.getName() + " (" + file.length() + " bytes) to server...");
            writeFile(file, socket.getOutputStream());
            System.out.println("Finished sending " + file.getName() + " to server");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void writeFile(File file, OutputStream outStream) {
        FileInputStream reader = null;
        try {
            reader = new FileInputStream(file);
            byte[] buffer = new byte[CHUNK_SIZE];
            int pos = 0;
            int bytesRead;
            while ((bytesRead = reader.read(buffer, 0, CHUNK_SIZE)) >= 0) {
                outStream.write(buffer, 0, bytesRead);
                outStream.flush();
                pos += bytesRead;
                System.out.println(pos + " bytes (" + bytesRead + " bytes read)");
            }
        } catch (IndexOutOfBoundsException e) {
            System.err.println("Error while reading file");
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("Error while writing " + file.toString() + " to output stream");
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经在这方面工作了几个小时,我几乎没有取得任何进展.我以为我对流的读/写工作有很好的理解,但显然我在这里遗漏了一些东西.

再次,当我从同一台机器发送和接收时,一切都很完美.但是如果我尝试在两台计算机之间发送文件,即使两台计算机位于同一个局域网上,我也会丢失很多已发送的数据.

任何人都可以找出我的问题吗?我已经尝试过我能想到的一切.

Ell*_*sch 5

您似乎正在混合分块数据和面向行的操作.我建议你DataInputStream在服务器上使用a ,然后使用a DataOutputStream.从客户端开始,类似于

private static void sendFile(String path) {
    if (path == null) {
        throw new NullPointerException("Path is null");
    }

    File file = new File(path);
    Socket socket = null;
    try {
        System.out.println("Connecting to server...");
        socket = new Socket(HOSTNAME, PORT);
        System.out.println("Connected to server at "
                + socket.getInetAddress());

        try (DataOutputStream dos = new DataOutputStream(
                new BufferedOutputStream(socket.getOutputStream()));) {
            dos.writeUTF(file.getName());
            dos.writeLong(file.length());

            System.out.println("Sending " + file.getName() + " ("
                    + file.length() + " bytes) to server...");
            writeFile(file, dos);
            System.out.println("Finished sending " + file.getName()
                    + " to server");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在服务器上

socket = server.accept();

DataInputStream dis = new DataInputStream(socket.getInputStream());
String name = dis.readUTF();
File file = new File(_downloadDir, name);
long fileSize = dis.readLong();
System.out.println("Saving " + file + " from user... ("
        + fileSize + " bytes)");
Run Code Online (Sandbox Code Playgroud)