通过套接字发送后,Jar文件已损坏



所以我正在构建一个需要内置自动更新功能的程序,因为我已经完成并对其进行了测试,似乎当我通过套接字发送 jar 文件并将其写入新制作的 jar 文件时,它缺少 5KB(每次......即使大小发生变化)大小从它变得损坏。

这是我的代码:

package server.update;
import java.io.*;
import java.net.Socket;
public class UpdateThread extends Thread
{
BufferedInputStream input; //not used
BufferedInputStream fileInput;
BufferedOutputStream output;
public UpdateThread(Socket client) throws IOException
{
    super("UpdateThread");
    output = new BufferedOutputStream(client.getOutputStream());
    input = new BufferedInputStream(client.getInputStream());
}
public void run()
{
    try
    {
        File perm = new File(System.getProperty("user.dir")+"/GameClient.jar");
        //fileInput = new BufferedInputStream(new FileInputStream(perm));
        fileInput = new BufferedInputStream(new FileInputStream(perm));
        byte[] buffer = new byte[1024];
        int numRead;
        while((numRead = fileInput.read(buffer)) != -1)
            output.write(buffer, 0, numRead);
        fileInput.close();
        input.close();
        output.close();
        this.interrupt();
    }
    catch(Exception e)
    {e.printStackTrace();}
}
}

这是将等待来自客户端的连接,然后在连接后立即将更新推送到它们的类。File Perm 是我想发送的 jar 文件,无论出于何种原因,它似乎错过了最后 5 个字节,或者客户端没有读取最后 5 个字节(我不知道是哪个)。以下是客户端在此处接收信息的类别:

public void getUpdate(String ip) throws UnknownHostException, IOException
{
    System.out.println("Connecting to update socket");
    update = new Socket(ip,10004);
    BufferedInputStream is = new BufferedInputStream(update.getInputStream());
    BufferedOutputStream os = new BufferedOutputStream(update.getOutputStream());
    System.out.println("Cleaning GameClient.jar file");
    File updated = new File(System.getProperty("user.dir")+"/GameClient.jar");
    if(updated.exists())
        updated.delete();
    updated.createNewFile();
    BufferedOutputStream osf = new BufferedOutputStream(new FileOutputStream(updated));
    System.out.println("Writing to GameClient.jar");
    byte[] buffer = new byte[1024];
    int numRead = 0;
    while((numRead = is.read(buffer)) != -1)
        osf.write(buffer, 0, numRead);
    System.out.println("Finished updating...");
    is.close();
    os.close();
    update.close();
    osf.close();
}

任何帮助,不胜感激。谢谢!

你的收盘价太多了。删除update.close()is.close(). 它们都会关闭套接字,从而防止缓冲流"osf"在关闭时自动刷新。关闭输入流或输出流或套接字将关闭另一个流和套接字。因此,您应该只关闭围绕套接字的最外层输出流,在这种情况下,osf,,也许套接字本身在 finally 块中以确保。

感谢 MDR 的回答,它奏效了!!

我不得不更改 UpdateThread 类中的以下代码行:

以前:

fileInput.close();
input.close();
output.close();
this.interrupt();

后:

fileInput.close();
output.flush();
output.close();
input.close();
this.interrupt();

您必须在关闭之前刷新流,我也切换了顺序,因为如果您关闭连接到套接字的输入流,它将关闭套接字,然后不会继续关闭输出流或刷新它。

再次感谢!

您是否考虑过使用 http 库将所有连接处理和读取/写入委托给已知的工作代码?你在这里重新发明了很多轮子。此外,在某些时候,您将希望确保您接收的内容是真实且未损坏的(您是通过加载类来做到这一点的,这有点危险,尤其是当您以明文形式交换数据时!同样,使用库及其方法将允许您选择HTTPS,从而允许TLS完成大部分工作。

我还建议您的服务器提前告诉客户端一些元数据,无论如何 - 也许是内容长度,也可能是哈希或校验和,以便客户端可以检测传输中的失败。

这个问题似乎也有与您的情况相关的答案。祝你好运!

最新更新