为什么socket只发送1KB(425B)的数据?

Why socket send only 1KB (425B) of data?

我正在学习套接字,现在想编写文件传输程序。我有服务器部分和客户端部分。服务器部分包含 2 个端口:5000(命令)和 5001(文件)。现在我想通过套接字发送一个文件,当我做错了,因为只有 425B 的数据正在发送。

客户端发送方法如下:

private void sendFile(Socket socket) {
    File file2 = new File("C:\Users\barte\Desktop\dos.png");
    byte[] bytes = new byte[16 * 1024];
    System.out.println(file2.exists());
    try (InputStream inputStream = new FileInputStream(file2);
        OutputStream outputStream = socket.getOutputStream();
        OutputStream secondOutput = new FileOutputStream("C:\Users\barte\Desktop\received\dos.png")) {
        int count;
        while ((count = inputStream.read(bytes)) > 0) {
            outputStream.write(bytes, 0, count);
            secondOutput.write(bytes, 0, count);
        }
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

如你所见(下图)我也在本地写这个文件,一切正常,73KB的数据全部写入。

现在,我正在服务器端尝试接收此文件:

case SEND: {
   new Thread(() -> {
     printWriter.println("Server is receiving files right now...");
     try (ServerSocket serverSocket = new ServerSocket(5001)) {
       while (true) {
        new FilesTransfer(serverSocket.accept()).start();
       }
     } catch (IOException e) {
        e.printStackTrace();
     }
     }).start();
     break;
   }

在 FilesTransfer 运行 方法中:

@Override
public void run() {
    System.out.println("Hello there");
    try {
        InputStream inputStream = inSocket.getInputStream();
        OutputStream outputStream = new FileOutputStream("C:\Users\barte\Desktop\received\file");
        byte[] bytes = new byte[16 * 1024];
        int count;
        while ((count = inputStream.read()) > 0) {
            outputStream.write(bytes, 0, count);
        }
        outputStream.close();
        inputStream.close();
        inSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

bug在哪里?为什么在本地一切正常时只发送空字节?

你可以这样做:

@Override
public void run() {
    System.out.println("Hello there");
    try {
        InputStream inputStream = inSocket.getInputStream();
        OutputStream outputStream = new FileOutputStream("C:\Users\barte\Desktop\received\file");
        byte[] bytes = new byte[16 * 1024];
        int byteRead= 1;
        while (byteRead > -1) {
            byteRead= inputStream.read();
            outputStream.write(byteRead);
        }
        outputStream.close();
        inputStream.close();
        inSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

实际上 END OF FILE 或 EOF 表示 -1 并且你做了 > 0 所以 0 被占用并且它停止了保存文件的连接。

我还建议编写一个逻辑将文件名作为命令传输到服务器,以便文件以正确的名称和扩展名保存!

问题是:

while ((count = inputStream.read()) > 0) {

您的代码使用 InputStream.read(),它读取单个字节(或 -1 在流结束时)。现在,您正在读取单个字节,将其解释为长度,然后将 bytes 中的 0x00 字节数写入文件。当您从流中读取 0x00 字节时停止。

您需要更改此设置才能使用 InputStream.read(byte[]):

while ((count = inputStream.read(bytes)) != -1) {

也就是说,你需要传入bytes,并检查结果是否不等于-1,而不是是否大于零(0),虽然read(byte[]) 只有 return 0 如果传入的字节数组的长度为零,所以这不是真正的问题。