通过单独计算机上的套接字发送大文件

时间:2018-11-01 14:36:33

标签: java sockets client-server

我创建了一个基本的客户端-服务器程序,该程序将文件从服务器传输到客户端。由于文件约为500MB,因此服务器通过DataOutputStream对象将文件作为字节块传输到客户端。虽然当客户端和服务器都在同一台计算机上运行时此逻辑可以正常工作,但是当两个程序在单独的计算机上运行时(两台计算机都在同一网络上,并且我都为两者禁用了防火墙),则该逻辑不起作用

在单独的计算机上运行时,问题在于传输了几个字节

服务器逻辑:

byte byteArr[] = new byte[1024];
while((c=fileInputStream.read(byteArr, 0, 1024) != -1))
{
    dataOutputStream.writeBoolean(true);
    dataOutputStream.flush();
    dataOutputStream.write(byteArr, 0, 1024);
    dataOutputStream.flush();
}
 /*When running on different computers, after a few hundred iterations 
   it just stops looping the following lines are never executed*/
dataOutputStream.writeBoolean(false);
System.out.println("Transfer complete");

客户端逻辑

byte byteArr[] = new byte[1024];
while(dataInputStream.readBoolean())
{
     dataInputStream.read(byteArr, 0, 1024);
     fileOutputStream.write(byteArr, 0, 1024);
}

1 个答案:

答案 0 :(得分:2)

不能保证read(buf, 0, 1024)调用准确地读取1024个字节。这会在两个代码段中引起错误:

  • 服务器错误地认为,从文件中读取的每个数据块总是正好1024个字节长,并将整个缓冲区发送给客户端。
  • 客户端可能不会在单个迭代中读取整个块。然后它将其余部分的第一个字节视为布尔值,并与服务器不同步。

要解决此问题,您可以:

  • 在发送文件之前发送文件大小(如果知道),  然后继续阅读,直到您阅读了那么多字节。

  • 或发送c(块大小)而不是单个布尔值,  然后使用dataInputStream.readFully()确保  许多字节将被读取。