怎样让socket接收端通过已知文件长度来接收文件

InfiniteP 2006-05-06 12:53:36
怎样实现让接收端通过已知文件长度来接收文件。发送端和接收端具体的实现方法?

原来我在文件传输过程中没有涉及文件长度,发送端发送完后,关了输出流,就自动关闭了Socket,无法继续发送其它文件。通过搜索相关问题答案,我考虑通过文件长度来传文件。

下面是我的部份代码:
----------------------------------------------------
发送方:
Socket socket_send;//已连接了对方
OutputStream ops = socket.getOutputStream();
DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream("待发送文件")));
DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(ops));
byte[] buf = new byte[1024];
while((dis.read(buf))!=-1)
{
dos.write(buf,0,buf.length);
}
dos.flush();
dos.close();//如果没有这句,接收方while((dis.read(buf))!=-1)将一直等待,就连文件数据传完了也不会退出while语句.但加了这句,就可以正确地发送该文件了,只不过发完后,socket也断开了,不能再重复发文件了......
---------------------------------------------------
接收方:
Socket socket_accept;//已连接了对方
InputStream ips=socket_accept.getInputStream();
BufferedInputStream br=new BufferedInputStream(ips);
DataInputStream dis= new DataInputStream(br);
DataOutputStream dos= new DataOutputStream(new BufferedOutputStream(new FileOutputStream("保存目录")));
byte[] buf = new byte[1024];
while((dis.read(buf))!=-1)//如果发送方没关闭输出流,则不会退出循环
{
dos.write(buf,0,buf.length);
}
dos.flush();
dos.close();
...全文
315 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
lhsoft 2006-05-16
  • 打赏
  • 举报
回复
mark
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
你好,yz790724(想想)。
我提的问题是:怎样让socket接收端通过已知文件长度来接收文件
我解决问题了之后,就急着结帖,结帖时,没见你的发言。虽然没机会给你加点分数,可还是要感谢你顶帖祝贺的。
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
我提问的目的就是想知道按长度收文件,即jshi123提供的这段代码:
while((bytes = dis.read(buf))!=-1 && totalBytes < fileLength)
{
dos.write(buf,0,buf.length);
totalBytes += bytes;
}
可能是我问题说得不清楚的原因,让你们一时不知道我问什么。

我说的这一要求“双方既能发文件又能收文件,还应该能让接收者选择接收或是不接收,选择接收后文件的保存目录”,原来就已经通过自定义传输协议的方式实现了。就是重复发送文件这块困扰了我好几天。今天总算在各位的帮助下解决了,心情放松多了。

我做的这个是我现在学士学位毕业设计题目---加密算法与数字签名技术的研究与实现。加密与签名部份实现之后,为了方便传输加密文件及密钥,我加了文件传输与聊天模块。文件传输与聊天放一起,同时用两个端口实现。

再次感谢你们的帮忙。特别是jshi123

追求自由 2006-05-06
  • 打赏
  • 举报
回复
祝贺
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
问题已经解决了,我按照你说的方法,并在发送端与接收端之间添加了两对同步标识(传输开始与传输结束)。就解决了这个问题。
  谢谢jshi123了。
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
收文件时,还是停在while中。
为了测试,我加了显示读的字节数
{
dos.write(buf,0,buf.length);
totalBytes += bytes;
System.out.println(bytes);
}
结果是,接收时,程序停在while中了,命令行显示的是一列1024,没有在最后显示小于1024的数。这是什么原因呢?
jshi123 2006-05-06
  • 打赏
  • 举报
回复
不必初始化,因为每次循环都会对其赋值:
while((bytes = dis.read(buf))!=-1 && totalBytes < fileLength)
即便有初值,执行到上述这条语句也被重新赋值了,所以接收方不能完全接收数据应该与初值无关。
接收方退出循环有两个条件:输入流关闭、和接收到足够数据,所以请注意发送方不要过早关闭输出或连接,希望有所帮助。
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
哦,是我看错了。不要初始化的。
但还是出现接收方没有完全接收数据的情况。
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
int bytes; // 每次循环读到的字节数
bytes应该初始化吧。照你的意思,是不是初始化为1024呢?可我将bytes值设为1024,总会出现接收方没有完全接收数据的错误。现在还在测试中,不知是否我的程序错误。
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
先谢谢jshi123
jshi123 2006-05-06
  • 打赏
  • 举报
回复
但其实我还是没有完全弄明白你的需求,上面的这段代码好像也没有能够解决你的问题,
因为靠上面的代码,是做不到“双方既能发文件又能收文件。还应该能让接收者选择接收或是不接收,及接收后文件的保存目录”。

另外,为什么每次发送时重新建立连接不实际,能说一下困难吗?
jshi123 2006-05-06
  • 打赏
  • 举报
回复
先尝试解答你的问题:

----------------------------------------------------
发送方:
Socket socket_send;//已连接了对方
OutputStream ops = socket.getOutputStream();
DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream("待发送文件")));
DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(ops));
dos.writeLong(new File("待发送文件").length()); // 先发送文件长度
byte[] buf = new byte[1024];
while((dis.read(buf))!=-1)
{
dos.write(buf,0,buf.length);
}
dos.flush();
//dos.close(); 你应当是不希望在输出流中写EOF的
---------------------------------------------------
接收方:
Socket socket_accept;//已连接了对方
InputStream ips=socket_accept.getInputStream();
BufferedInputStream br=new BufferedInputStream(ips);
DataInputStream dis= new DataInputStream(br);
DataOutputStream dos= new DataOutputStream(new BufferedOutputStream(new FileOutputStream("保存目录")));
long fileLength = dis.readLong(); // 先读取文件长度
long totalBytes = 0; // 已读取的字节数
int bytes; // 每次循环读到的字节数
byte[] buf = new byte[1024];
while((bytes = dis.read(buf))!=-1 && totalBytes < fileLength)//如果发送方没关闭输出流,并且未读取足够数据,则不会退出循环
{
dos.write(buf,0,buf.length);
totalBytes += bytes;
}
// 即时发送方未关闭输出,只要读取指定的字节数后,便能退出循环
dos.flush();
dos.close();

上面的方法是通过先发送文件长度,接收方接收到指定的长度数据后,在发送方不关闭连接的情况下,退出循环。
不知道你所说的“通过已知文件长度来接收文件”是否指的这个。
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
我现在把我要解决的问题简述一下吧:
在双方已建立socket连接,并且接收方已经知道要接收多大文件的前提下,怎样具体实现接收端接收文件。
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
每次发送时重新建立连接,不实际啊。
jshi123 2006-05-06
  • 打赏
  • 举报
回复
按你的要求看,最简单的方法是每次发送一个文件,每次发送时重新建立连接-〉传送数据-〉关闭。
files是String数组,用来存放一组文件名,files.length指文件的数量
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
jshi123:
files.length是批量发送的文件数目吧,不是单个文件的文件长度吧?
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
其实我要实现的是双方既能发文件又能收文件。还应该能让接收者选择接收或是不接收,及接收后文件的保存目录。现在我大部份问题已解决,就是如果接收了话,发送端只能关闭输出流,要不然就连一个文件也发送失败。而发送端传完文件后,立即关闭输出流的话,socket也随之断开了。
jshi123 2006-05-06
  • 打赏
  • 举报
回复
如果只是需要发送多个文件,可以在所有文件发送完成后关闭连接即可:

----------------------------------------------------
发送方:
Socket socket_send;//已连接了对方
OutputStream ops = socket_send.getOutputStream();
String[] files = ...;
for (int i=0; i<files.length; i++)
sendFile(ops, files[i]);
ops.close();

void sendFile(OutputStream ops, String file) throws IOException {
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(ops));
byte[] buf = new byte[1024];
while((dis.read(buf))!=-1)
{
dos.write(buf,0,buf.length);
}
dos.flush();
}

然则你要解决的问题似乎并非只是“发送多个文件”? ...
InfiniteP 2006-05-06
  • 打赏
  • 举报
回复
能具体点吗?我想知道如何在接收方已经知道长度的情况下,如何用代码实现接收该长度文件。还要能继续接收其它文件。
f_acme 2006-05-06
  • 打赏
  • 举报
回复
发送方可以在发送之前先发送一个文件长度的消息给接受端,然后再发送文件啊。
你看http协议下载的时候是先获得要传输文件的长度信息的。
加载更多回复(2)

62,614

社区成员

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

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