【问题标题】:Error sending file through java socket通过java套接字发送文件时出错
【发布时间】:2015-07-24 03:01:44
【问题描述】:

我在通过套接字 java 发送文件时遇到问题。有时代码有效,有时无效。我在两者中都测试了 while 块,似乎代码正在发送所有字节,但服务器没有接收到(但即使在这个测试中,文件也被正确发送)。在这种情况下,服务器停止接收数据。所有文件大约150Kb。我使用的是 9191 端口。

服务器:

while (true) {
        try {
            Socket socket = ss.accept();
            ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
            String fileName = in.readUTF();

            FileOutputStream fos = new FileOutputStream(destinationPath + fileName);
            byte[] buf = new byte[1024];

            int len;
            while ((len = in.read(buf)) >= 0) {
                fos.write(buf, 0, len);
            }
            fos.flush();

        } catch (Exception ex) {
            ex.printStackTrace();
        }
}

客户:

    try {
        Socket socket = new Socket(host, port);
        ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

        out.writeUTF(file.getName());
        out.writeLong(file.length());
        FileInputStream in = new FileInputStream(file);
        byte[] buf = new byte[1024];

        int len;
        while ((len = in.read(buf)) >= 0) {
            out.write(buf, 0, len);
        }

        out.close();
        socket.close();

    } catch (Exception e) {
        throw e;
    }

【问题讨论】:

    标签: java file sockets send


    【解决方案1】:

    在你说的客户上,

    out.writeUTF(file.getName());
    out.writeLong(file.length());
    

    但是在你说的服务器上,

    String fileName = in.readUTF();
    FileOutputStream fos = new FileOutputStream(destinationPath + fileName);
    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) >= 0) {
        fos.write(buf, 0, len);
    }
    fos.flush();
    

    您没有读取文件长度。并且您需要确保您读取了所有发送的字节(否则您的文件将被损坏)。另外,不要忘记close()FileOutputStream(或使用try-with-resources 为您关闭它)。类似的,

    String fileName = in.readUTF();
    try (FileOutputStream fos = new FileOutputStream(destinationPath
            + fileName)) {
        long size = in.readLong();
        byte[] buf = new byte[1024];
        long total = 0;
        int len;
        while ((len = in.read(buf)) >= 0) {
            fos.write(buf, 0, len);
            total += len;
        }
        if (total != size) {
            System.err.printf("Expected %d bytes, but received %d bytes%n",
                    size, total);
        }
    }
    

    【讨论】:

    • 我进行了更改并意识到它发送了 1 个文件,而服务器上的第二个(相同或不同)文件的代码在“while ((len = in.read( buf)) >= 0) {",因为我在块后面放了一个 println,它不会在第二次显示。
    • 确保您正在发送另一个文件...上面的代码发送 1 个文件(不是多个文件 - 并且客户端发布了调用 socket.close();
    • 事实上,在 localhost 中有效,但在远程 ubuntu 服务器中则无效。我清除了 iptables 规则,什么也没有。在这种情况下,我发送一个文件,几秒钟后发送另一个文件,再次调用 SocketClient
    • 再次调用 SocketClient 是什么意思?一旦您调用socket.close(),您不能在不重新连接的情况下使用socket。同样,一旦你调用out.close(),你就不能在不重新连接的情况下使用socket.getOutputStream()中的OutputStream(出于同样的原因)。
    • 所以,我每次要发送文件时都会实例化 SocketClient。在这种情况下,我循环调用 SocketClient N 次。我认为在这种情况下在 SocketClient 中调用 socket.close() 不是问题。
    【解决方案2】:

    首先,您应该将ObjectInputStreamObjectOutputStream 分别替换为DataInputStreamDataOutputStream。您没有序列化 java 对象,因此使用流类是没有意义的。

    其次,您在客户端发送文件长度,但没有专门在服务器中读取它。它被添加到文件的开头。

    【讨论】:

    • 我进行了更改并意识到它发送了 1 个文件,而服务器上的第二个(相同或不同)文件的代码在“while ((len = in.read( buf)) >= 0) {",因为我在块后面放了一个 println,它不会在第二次显示。
    • @Marcelo 如果你想从客户端向服务器发送多个文件,我建议首先发送一个 int 值,告诉服务器需要多少个文件。然后对于每个文件以文件名开头,然后是它的大小,然后是大小字节。在读取文件名的服务器上,它的大小然后将 size 字节从流复制到文件并重复直到文件用完。
    • 事实上,在 localhost 中有效,但在远程 ubuntu 服务器中则无效。我清除了 iptables 规则,什么也没有。在这种情况下,我发送一个文件,几秒钟后,另一个文件。
    • 远程尝试时遇到什么错误?
    • 没什么。它在 while 循环内部停止并且什么也不做。我在内部放置消息,突然它停止显示消息
    猜你喜欢
    • 2013-12-15
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 2011-02-24
    相关资源
    最近更新 更多