通过Socket连接一次传输多个文件
近期在做一个通过WIFI在手机之间传输文件的功能。须要在手机之间建立一个持久的Socket
连接并利用该连接数据传输。能够一次传输一个或多个文件。
在一次传输多个文件时,遇到了一个困难:怎样在接收文件时确定文件之间的边界。
为了在接收端正确的拆分文件,在传输文件时须要传输每一个文件的大小。
我採用了这样一种策略:首先发送每一个文件的名称和大小。然后传输文件的内容。
protected void sendFile(Socket socket, File[] files) {
long totalSize = 0;
byte buf[] = new byte[8192];
int len;
try {
if (socket.isOutputShutdown()) {
return;
}
DataOutputStream dout = new DataOutputStream(
socket.getOutputStream());
dout.writeInt(files.length);
for (int i = 0; i < files.length; i++) {
dout.writeUTF(files[i].getName());
dout.flush();
dout.writeLong(files[i].length());
dout.flush();
totalSize += files[i].length();
}
dout.writeLong(totalSize);
for (int i = 0; i < files.length; i++) {
BufferedInputStream din = new BufferedInputStream(
new FileInputStream(files[i]));
while ((len = din.read(buf)) != -1) {
dout.write(buf, 0, len);
}
}
System.out.println("文件传输完毕");
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG,"send file exception");
}
return;
}
接收文件时有些复杂。每次从输入流中读入缓存中的数据有可能包括多个文件的内容,
须要利用每一个文件的大小信息把缓存中的数据放入不同的文件。
protected void receiveFile(Socket socket) {
File dirs = new File(mFilePath);
if (!dirs.exists()) {
dirs.mkdirs();
}
DataInputStream din = null;
int fileNum = 0;
long totalSize = 0;
FileInfo[] fileinfos = null;
try {
din = new DataInputStream(new BufferedInputStream(
socket.getInputStream()));
fileNum = din.readInt();
fileinfos = new FileInfo[fileNum];
for (int i = 0; i < fileNum; i++) {
fileinfos[i] = new FileInfo();
fileinfos[i].mFileName = din.readUTF();
fileinfos[i].mFileSize = din.readLong();
}
totalSize = din.readLong();
} catch (IOException e) {
e.printStackTrace();
Log.d(TAG,"readInt Exception");
System.exit(0);
}
System.out.println(fileNum);
System.out.println(totalSize);
for (FileInfo fileinfo : fileinfos) {
System.out.println(fileinfo.mFileName);
System.out.println(fileinfo.mFileSize);
}
// // /////////////////////////////////////////////////////////////////
int leftLen = 0; // 写满文件后缓存区中剩余的字节长度。
int bufferedLen = 0; // 当前缓冲区中的字节数
int writeLen = 0; // 每次向文件里写入的字节数
long writeLens = 0; // 当前已经向单个文件里写入的字节总数
long totalWriteLens = 0; // 写入的所有字节数
byte buf[] = new byte[8192];
for (int i = 0; i < fileNum; i++) {
writeLens = 0;
try {
FileOutputStream fout = new FileOutputStream(mFilePath
+ fileinfos[i].mFileName);
while (true) {
if (leftLen > 0) {
bufferedLen = leftLen;
} else {
bufferedLen = din.read(buf);
}
if (bufferedLen == -1)
return;
System.out.println("readlen" + bufferedLen);
// 假设已写入文件的字节数加上缓存区中的字节数已大于文件的大小,仅仅写入缓存区的部分内容。
if (writeLens + bufferedLen >= fileinfos[i].mFileSize) {
leftLen = (int) (writeLens + bufferedLen - fileinfos[i].mFileSize);
writeLen = bufferedLen - leftLen;
fout.write(buf, 0, writeLen); // 写入部分
totalWriteLens += writeLen;
move(buf, writeLen, leftLen);
break;
} else {
fout.write(buf, 0, bufferedLen); // 所有写入
writeLens += bufferedLen;
totalWriteLens += bufferedLen;
if (totalWriteLens >= totalSize) {
//mListener.report(GroupChatActivity.FAIL, null);
return;
}
leftLen = 0;
}
//mListener.report(GroupChatActivity.PROGRESS,
//(int) (totalWriteLens * 100 / totalSize));
} // end while
fout.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d(TAG,"receive file Exception");
}
} // end for
//mListener.report(GroupChatActivity.FAIL, null);
}
注:在传输文件时还传输了文件的总大小,这样为了在接收文件时判定接收是否结束。
另一种传输方法比較复杂但更加灵活发送文件时依次传输每一个文件的名称。大小和内容。
相比上一个方法这样的发送方式接受时更难处理。
由于每次从输入流中读入缓存的数据可能包括了上一个文件的内容。下一个文件的名称和大小。
因为数据已被读入了缓存,这就不能利用DataInputStream的方法读取UTF字符串和Int,
必须从缓存中解析。
介绍两种解析方法
利用ByteArrayInputStream 把缓存中的内容转化为内存流然后利用DataInputStream读取。
手动解析,利用位运算拼接出Int。
注:Int 的长度为4是确定的。
WriteUTF 写入的字串长度存储在開始的两个字节中。
通过Socket连接一次传输多个文件的更多相关文章
- 对于.NET Socket连接的细节记录
如果客户端直接连接一个不存在的服务器端,客户端会抛出异常: 如果在连接过程中,客户端强制关闭了连接(没有调用Close直接关闭了程序),服务器端会抛出异常: 如果在连接过程中,客户端调用了Close, ...
- 比较 http连接 vs socket连接
http连接 :短连接,客户端,服务器三次握手建立连接,服务器响应返回信息,连接关闭,一次性的socket连接:长连接,客户端,服务器三次握手建立连接不中断(通过ip地址端口号定位进程)及时通讯,客户 ...
- UrlConnection连接和Socket连接的区别
关于UrlConnection连接和Socket连接的区别,只知道其中的原理如下: 抽象一点的说,Socket只是一个供上层调用的抽象接口,隐躲了传输层协议的细节. urlconnection 基于H ...
- 转 Cocos网络篇[3.2](3) ——Socket连接(1)
Cocos网络篇[3.2](3) ——Socket连接(1) 2015-03-05 22:24:13 标签:network http socket cocos [唠叨] 在客户端游戏开发中,使用HTT ...
- Http和Socket连接区别
相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 要想明白Socket连接,先要明白TCP连接.手机能够使用联 ...
- Http、tcp、Socket连接区别
转自Http.tcp.Socket连接区别 相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 要想明白Sock ...
- Socket连接与HTTP连接
我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP.FTP.T ...
- Http和Socket连接的区别
Http和Socket连接区别 相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 要想明白Socket连接,先 ...
- Http和Socket连接
转自http://hi.baidu.com/%D2%B9%D1%A9%B3%E6/blog/item/d6a72d2bbf467cf2e7cd406d.html 相信不少初学手机联网开发的朋友都想知道 ...
随机推荐
- Java高级架构师(一)第35节:Nginx的Location区段
没有修饰符 表示:必须以指定模式开始. 表示/abc下的所有内容都可以被访问. = 表示与指定的模式精确匹配,可以带参数. 实例中要求区分大小写,并以c结尾. 实例中指定的正则表达式不区分大小写. 注 ...
- Educational Codeforces Round 9 E. Thief in a Shop dp fft
E. Thief in a Shop 题目连接: http://www.codeforces.com/contest/632/problem/E Description A thief made hi ...
- Font Include Sass Mixin
前端开发whqet,csdn,王海庆,whqet,前端开发专家 前期以前给大家介绍过一个使用google font的mixin(详见<Google Fonts Sass Mixin>),今 ...
- 【UEditor】关于导入ueditor-1.1.3.jar的问题---
最近做一个项目,使用了百度的富文本框,本来是很简便易用的东西,在回显给富文本框的时候, var ue = UE.getEditor('container'); var noticeContent = ...
- Pod中访问外部的域名配置
在实际应用中经常遇到Pod中访问外部域名的状况,在Kubenetes 1.6以上的版本通过配置DNS configmap已经解决,详细的内容可以参考官方的 https://kubernetes.io/ ...
- 定制你自己的CRF模型
如何训练自己的CRF模型 Ansj从5.0版本之后支持训练自己的crf模型,在此之前虽然已经很早支持了CRF模型,但是在用户的自训练上要求苛刻,而且本身实现的CRF从性能到准确率都不如CRF++或者第 ...
- Spring @Autowired 注解不生效
@Autowired默认不生效.为了生效,需要在xml配置:<context:annotation-config> 注解一<context:component-scan base-p ...
- Linux系统下,启动Tomcat有时报Address already in use
一.Linux系统下,启动Tomcat有时报Address already in use<null>... 1.那是因为你的tomcat已经启动了tomcat自带的关闭脚本,有时候关闭看上 ...
- phpstorm不安装apache就可以本地测试PHP
最近再搞个PHP的项目,找了很多发现phpstorm这个非常小巧而且很好用,,顺便推荐一下idea开发android非常不错,这2个IDE都是一家公司的.本文由智动软件(zdexe.com)原创,转载 ...
- 流畅的python第十八章使用asyncio包处理并发
对比一个简单的多线程程序和对应的 asyncio 版,说明多线程和异步任务之间的关系asyncio.Future 类与 concurrent.futures.Future 类之间的区别摒弃线程或进程, ...