所以我正在构建一个需要内置自动更新功能的程序,因为我已经完成并测试了它,似乎当我将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();
}
感谢任何帮助。谢谢!
答案 0 :(得分:2)
你关闭太多了。删除update.close()
和is.close().
这两个都关闭套接字,这可以防止缓冲流'osf'在关闭时自动刷新。关闭输入流或输出流或套接字将关闭另一个流和套接字。因此,您应该只关闭缠绕在套接字上的最外面的输出流,在本例中为osf,
,并且可能是最后一个块中的套接字本身。
答案 1 :(得分:0)
感谢MDR的回答,它有效!!
我必须在UpdateThread类中更改以下代码行:
在:
fileInput.close();
input.close();
output.close();
this.interrupt();
后:
fileInput.close();
output.flush();
output.close();
input.close();
this.interrupt();
你必须在关闭前刷新流,我也切换了订单,因为如果关闭连接到套接字的输入流,它将关闭套接字,然后不会继续关闭输出流或刷新它。
再次感谢!
答案 2 :(得分:-2)
您是否考虑过使用http library将所有连接处理和读/写委托给已知的工作代码?你在这里重新发明了很多轮子。此外,在某些时候,您将要确保您收到的内容是真实且完好无损的(您通过加载课程来实现这一点,这有点危险,尤其是当您以明文形式交换数据时!) ,使用库及其方法将允许您选择HTTPS,允许TLS完成大部分工作。
我还建议您的服务器提前告诉客户端一些元数据 - 无论是内容长度还是散列或校验和,以便客户端可以检测传输中的失败。
This question似乎也有与您的情况相关的答案。祝你好运!