Android 中 Socket 基于TCP 传输大文件

5 篇文章 0 订阅

Android 客户端:

1. 创建Socket对象

Socket socket = new Socket();

 

2.创建连接到指定的主机、端口

socket.connect(new InetSocketAddress("10.10.10.100", 980));

 

3.创建File对像,并指定要传输的文件绝对路径

File f=new File("/sdcard2/AppManage.apk");

 

如果需要用断点继传需要用这个RandomAccessFile对象

//RandomAccessFile fileOutStream = new RandomAccessFile(f, "r");
//"r":以只读文方式打开指定文件。如果你写的话会有IOException。
//"rw":以读写方式打开指定文件,不存在就创建新文件。

 

4.将文件绑定到InputStream流对象

InputStream fileOutStream = new FileInputStream(f);

 

5.创建OutputStream对象

OutputStream outputStream = socket.getOutputStream();

 

如果需要用断点继传需在这里设定跳过的字节。

//fileOutStream.seek(sek);

 

6.获取文件总长度

long count = fileOutStream.available();

上面可能读不到文件的总长度,因为读取时需要时间,如果SD卡质量不好可能要等待一会。

所以最好加上这一句

while(count == 0){
       count = fileOutStream.available();
 }

如果是用断点继传用这个获取文件总长度

long count = fileOutStream.length();

 

7. 将文件总字节数写入到流中,这里要做一个long转成8个字节的转换

byte[] totalCount = new byte[8]; //将总数转为byte字符
outputStream.write(totalCount);

 

8. 指定每包大小字节和计算包数   -2,147,483,648 到  2,147,483,647

int PacketSize = 10240;//这里指定每包为10Kbyte

int PacketCount = (int)(count / ((long)PacketSize));//总包数

int LastDataPacket = (int)(count - ((long)(PacketSize * PacketCount)));//余字节数,也可能会是0

 

9.循环将包写入到流中

byte[] buffer = new byte[PacketSize];//设定缓冲区
for(int i=0; i<PacketCount; i++){

     fileOutStream.read(buffer,0,buffer.length);//将文件读到缓冲区
      byte[] bufferLength = new byte[4]//需要将buffer的长度转换为byte字节
      outputStream.write(bufferLength);//写入4个字节代表buffer的长度
      outputStream.write(buffer);//将缓冲写入到流

}

 

10.写入余字节数

if(LastDataPacket != 0){
      buffer = new byte[LastDataPacket];//重新设定缓冲区大小
      fileOutStream.read(buffer,0,buffer.length);将文件读到缓冲区
      byte[] bufferLength = new byte[4]//需要将buffer的长度转换为byte字节
      outputStream.write(bufferLength);//写入4个字节代表buffer的长度
      outputStream.write(buffer);//将缓冲写入到流
}

 

11. 最后关闭和刷新

outputStream.flush();

fileOutStream.close();
outputStream.close();

需要注意的是,如果未按7章中写入文件总字节到流中服务器就不会知道文件的大小,导致只能一直接收并写入到文件中,并且

需要客户端关闭时才会停止,没办法回复信息。

 

服务器端(用C#写的服务器端),主要解释将流写入到文件

1.创建文件对象FileStream

FileStream MyFileStream = new FileStream("保存路径", FileMode.Create, FileAccess.Write);
如果是断点继传,需要用下面的方式

FileStream MyFileStream = new FileStream("保存路径", FileMode.Append, FileAccess.Write);
MyFileStream.Seek(0, SeekOrigin.Begin);

 

2.读取文件总字节

byte[] total = new byte[8];//创建缓冲区
Receive(total, 0, 8, SocketFlags.None);//读到8个字节位置

long totalCoun = BitConverter.ToInt64(total, 0);//转换成long

 

3.循环读取流并写入到文件

while (true) {
        //循环读取,每次读到包指定位置
        byte[] data = ReceiveVarData(client);
         if (data.Length == 0) {
             break;//读取0时退出
          } else {

              //写入到文件中
              MyFileStream.Write(data, 0, data.Length);
          }
}

//关闭
MyFileStream.Close();

 

最后是ReceiveVarData的方法,也是关键部份

public byte[] ReceiveVarData(Socket s){
            int total = 0;
            int recv;
            byte[] datasize = new byte[4];//创建缓冲区
            recv = s.Receive(datasize, 0, 4, SocketFlags.None);//读到4个字节位置
            int size = BitConverter.ToInt32(datasize, 0);//转换为int

            int dataleft = size;
            byte[] data = new byte[size];//创建当前要接收的大小缓冲区

           因为网络可能会堵塞,这里也要做循环判断。
            while (total < size) {
                recv = s.Receive(data, total, dataleft, SocketFlags.None);//开始读取
                if (recv == 0) {
                    data = null;
                    break;
                }
                total += recv;
                dataleft -= recv;
            }
            return data;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值