关于自定义协议利用SOCKET传输文件

goujunfu0822 2014-05-06 03:01:25
首先要说明,因为我不会去关闭服务器上的流和客户端的流,因为我想让客户端利用一个socket随意传递数据,不限次数
不能关闭流,那么不能通过while判断read是否返回-1来判断文件是否传递完毕。所以我采用提前告诉客户端文件大小,来决定服务器和客户端的write和read次数,但是却造成服务器发送的文件还没发送完,客户端就已经使用完所有read次数了
为了方便大家看,我截取重要代码,下面这里是服务器发送文件的代码
private void sendFile(String filePath, BufferedWriter bw)
throws IOException {
File file = new File(filePath);
if (!file.exists()) {
return;
}
// 文件读取流
BufferedInputStream bin = new BufferedInputStream(
new FileInputStream(file));

// 发送Head
bw.write("file,"+file.length()+"\n");
bw.flush();
byte[] b = new byte[8192];
int i=0;
int sum;
while ((sum = bin.read(b)) != -1) {
out.write(b,0,sum);
System.out.println("server"+i+"====>>>"+sum+"====>"+(file.length()));
i++;
out.flush();
}
out.flush();
System.out.println("传输完毕");
bin.close();
}
}

这里是客户端接受文件代码
long count = Long.parseLong(data.split(",")[1]);
long time;
if (count % 8192 == 0)
time = count / 8192;
else
time = count / 8192 + 1;

BufferedOutputStream bout = new BufferedOutputStream(
new FileOutputStream("G:\\text.chm"));

int sz;
byte[] b = new byte[8192];
for (int i = 0; i < time; i++) {
sz = in.read(b);
bout.write(b, 0, sz);
System.out.println("client:"+i + "/" + time+"======>>"+sz);
}

System.out.println("下载完成");
bout.flush();
bout.close();
...全文
520 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
vnvlyp 2014-05-16
  • 打赏
  • 举报
回复
一个好的文件传输协议是需要完善的实现的,你这个协议太粗糙了吧。。
请参考FTP,TFTP协议。
附一个TFTP协议的报文格式可以参考
chichenzhe 2014-05-16
  • 打赏
  • 举报
回复
引用 2 楼 goujunfu0822 的回复:
[quote=引用 1 楼 rumlee 的回复:] 你把数组定义成8192,不代表你每次读取的字节就是8192,这是两回事,每次读取你都要根据read方法返回值才能够确定实际读取了多少个字节。
那我应该如何确定客户端需要read多少次,从这边的控制台输出结果来看,客户端好像每次还是读取了8192但是还是没有读取完,服务器最后一次发送的字节数是6000+,但是客户端最后的读取字节数还是8192,是否在我不知道的时候,服务器的write在我没调用flush的时候又悄悄发送了数据[/quote] socket 要写得比较好 是个庞大的话题. 虽然有mina等开源jar可用 但依然是个庞大的话题. 所以.. 目前你最需要的还是补足这方面知识. 1.你不能确定客户端read多少次. 根据不同的 mtu 以及包的转发规则, 最后一个 8192的数据会分成多少个碎片到达终端很难确定. 2.服务器不会神出鬼没般的给客户端随意发数据过去. (这又不是神话传说) 3.如果你仅仅是要定关于 8192字节这么个简单的协议的话. 我建议你这么干: *) 服务器不管什么情况下(无论需要不需要发这么多数据) 都固定的一次发8192字节. 然后客户端while循环去读这8192 4.如果想写得比较好我建议你这么干: *) 定义一个包长在前2个字节里(short) *) 客户端先接这个short, 再while循环去读取这 short个字节.
woshilisao 2014-05-16
  • 打赏
  • 举报
回复
长连接要注意粘包、分包的问题
goujunfu0822 2014-05-06
  • 打赏
  • 举报
回复
引用 1 楼 rumlee 的回复:
你把数组定义成8192,不代表你每次读取的字节就是8192,这是两回事,每次读取你都要根据read方法返回值才能够确定实际读取了多少个字节。
那我应该如何确定客户端需要read多少次,从这边的控制台输出结果来看,客户端好像每次还是读取了8192但是还是没有读取完,服务器最后一次发送的字节数是6000+,但是客户端最后的读取字节数还是8192,是否在我不知道的时候,服务器的write在我没调用flush的时候又悄悄发送了数据
rumlee 2014-05-06
  • 打赏
  • 举报
回复
你把数组定义成8192,不代表你每次读取的字节就是8192,这是两回事,每次读取你都要根据read方法返回值才能够确定实际读取了多少个字节。
lliiqiang 2014-05-06
  • 打赏
  • 举报
回复
提前获知文件大小告诉客户端.

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧