【问题标题】:send multiple files with JAVA socket [duplicate]使用JAVA套接字发送多个文件[重复]
【发布时间】:2019-07-17 17:56:00
【问题描述】:

我想通过套接字连接发送多个文件。对于一个文件,它可以完美运行,但如果我尝试发送多个(一次一个),我会收到Socket Exception

java.net.SocketException: 套接字关闭

一般来说,我的连接是这样工作的:

  1. 服务器等待连接
  2. 客户端连接到服务器并发送对某个文件的请求(包含文件名的字符串)
  3. 服务器读取本地文件并发送给客户端
  4. 客户端发送另一个文件的另一个请求并在第 3 点继续。

waiting-for-request 过程的运行方法如下所示:

@Override
public void run() {
    String message;
    try {
        while ((message = reader.readLine()) != null) {

            if (message.equals(REQUESTKEY)) {
                System.out.println("read files from directory and send back");
                sendStringToClient(createCodedDirContent(getFilesInDir(new File(DIR))), socket);
            } else if (message.startsWith(FILE_PREFIX)) {

                String filename = message.substring(FILE_PREFIX.length());
                try {
                    sendFile(new File(DIR + filename));
                } catch (IOException e) {
                    System.err.println("Error: Could not send File");
                    e.printStackTrace();
                }
            } else {
                System.out.println("Key unknown!");
            }
        }
    } catch (Exception ex) {

        ex.printStackTrace();
    }
}

而我的sendFile() 方法看起来像这样:

public void sendFile(File file) throws IOException {
    FileInputStream input = new FileInputStream(file);
    OutputStream socketOut = socket.getOutputStream();

    System.out.println(file.getAbsolutePath());
    int read = 0;
    while ((read = input.read()) != -1) {
        socketOut.write(read);
    }
    socketOut.flush();

    System.out.println("File successfully sent!");

    input.close();
    socketOut.close();
}

我认为问题在于socketOut.close()。不幸的是,该方法也关闭了套接字连接(进一步连接的问题)。但是,如果我忽略此关闭,则文件传输将无法正常工作:文件到达客户端时不完整。

如何避免或解决此问题?或者有没有更好的方法来传输多个请求的文件?

谢谢

【问题讨论】:

  • 您需要告诉您的客户文件有多大。否则,您只是在流式传输字节,没有尽头。客户不知道何时停止阅读。想想两者之间的通信(协议)。

标签: java sockets file-transfer


【解决方案1】:

我已经稍微改写了您的发送文件方法,以便您可以发送多个文件,您需要将其传递给 DataOutputStream 并在发送完所有要发送的文件后关闭流。

读取时,您应该使用DataInputStream 并调用long len = dis.getLong(),然后从流中读取len 字节,然后重复下一个文件。您可能会发现在开始时发送文件数量很有用。

public void sendFile(File file, DataOutputStream dos) throws IOException {
    if(dos!=null&&file.exists()&&file.isFile())
    {
        FileInputStream input = new FileInputStream(file);
        dos.writeLong(file.getLength());
        System.out.println(file.getAbsolutePath());
        int read = 0;
        while ((read = input.read()) != -1)
            dos.writeByte(read);
        dos.flush();
        input.close();
        System.out.println("File successfully sent!");
    }
}

【讨论】:

  • 谢谢!这就是我想要的,它现在可以工作了:)
  • 问题是关于通过单个套接字连接发送多个文件。很难看出这有什么资格作为答案。这也是极其低效的。
  • @EJP 如果您仔细检查代码,它只会关闭FileInputStream,而不是DataOutputStream,所以我不确定您希望如何编写更高效的协议(缺少即时压缩文件)。此外,DataOutputStream 是使用来自套接字的 getOutputStream() 方法构造的,传递流比继续重建流更好(IMO)。所以我不确定他们问题的哪一部分没有回答,特别是考虑到问题作者的回答。
【解决方案2】:

您可以在客户端和服务器之间定义一个简单的协议。在文件内容之前发送文件长度。使用 DataOutputStream / DataInputStream 发送/读取长度。不要在每个文件之后关闭套接字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2012-11-13
    • 2015-10-01
    • 1970-01-01
    • 2020-05-22
    • 2019-06-26
    相关资源
    最近更新 更多