我有Java SSL / TLS服务器和客户端套接字。我的客户端只是将文件发送到服务器,服务器接收它。这是我的代码:
我的客户端方法:
static boolean writeData(BufferedOutputStream bos, File data) {
FileInputStream fis = new FileInputStream(data);
BufferedInputStream bis = new BufferdInputStream(fis);
byte[] bytes = new byte[512];
int count = 0;
while ((count = bis.read(bytes, 0, bytes.length)) > 0) {
System.out.println("Sending file...");
bos.write(dataByte, 0, count);
System.out.println(count);
}
bos.flush();
System.out.println("File Sent");
}
我的服务器方法:
static boolean receiveData(BufferedInputStream bis, File data) {
byte[] bytes = new byte[512];
int count = 0;
while ((count = bis.read(bytes, 0, bytes.length)) > 0) {
System.out.println("Receiving file...");
// Do something..
System.out.println(count);
}
bos.flush();
System.out.println("File Received");
}
问题是,服务器在while循环内挂起..它永远不会到达“File Received”消息。
即使文件很小,bis.read()方法也不会因为某种原因在文件末尾返回-1。我测试了文件大小为16字节的方法,输出如下:
客户终端:
> Sending file...
> 16
> File Sent
服务器终端:
> Receiving file...
> 16
正如您所看到的,服务器永远不会到达“文件已接收”消息,并且即使在到达流末尾之后也会在循环内挂起..有人可以猜出原因吗?
由于
答案 0 :(得分:2)
您的服务器从未检测到该文件已被发送,因为它会检查您是否已关闭另一端的连接(这是您接收-1字节读取的唯一原因)。
但你永远不会关闭连接,只能冲洗它。
将bos.flush()
替换为bos.close()
方法中的writeData
,它应该有效。
如果您不想关闭连接,因为您想要更多地使用它,您必须添加某种协议,因为没有默认方式去做。
您可以做的一件事,就是实现此目的的一种更简单的方法,就是在文件之前将文件的长度发送为32位或64位整数。 / p>
然后服务器知道它应该读取多少字节才能认为文件已完全发送。 如果你不知道文件的长度,有很多选择。我不确定是否就最有效的方法达成共识,但鉴于许多协议采用不同的方法,我不认为存在。 这些只是一些建议,您可以调整。
0xFF
0xFF
表示文件已结束的规则,但0xFF
0x00
表示"只是文字0xFF"在文件中。