写了很久的Android、pc文件无线双向传输开发,要开发Android的app和电脑的软件,用tco协议在局域网内互相传输文件。
中间遇到不少问题,把遇到的问题和解决的方法的罗列一下。
一.socket的问题。
在android的app上,我把连接socket,发送文件和接收文件分成三个类,而且本身对tcp双向传输不熟,所以这部分就遇到很多问题。
1.socket在类之间传递
首先在socket连接类上连接socket并写个方法传递socket,
接着在main.java上调用并传递socket给另两个类,
另外两个类上用同一个方法介绍socket
public void setSocket(Socket temp) { socket = new Socket(); socket = temp; }
2.
socket如果要一直连着就不能close掉。
发送文件类的OutputStream out = socket.getOutputStream();,的out不能close掉
接收文件的DataInputStream in = new DataInputStream(socket.getInputStream());也不能close掉
3.因为接收文件要一直监听,发送只需要在发送的时候发送,所以socket调用时也有所不同
发送类:
public void start(final String filePath) { //send(filePath); new Thread() { @Override public void run() { sendFlag = true; while (sendFlag) { send(filePath); sendFlag =false; } } }.start(); }
private void send(String filePath) { //work here!!!!!!!!!!!!!broken pipe try { Log.v("send", "send start"); OutputStream out = socket.getOutputStream(); File file = new File(filePath); String fileName = file.getName(); Log.v("send fileName", fileName); ......
{ @Override public void run() { while(true) { try { in = new DataInputStream(socket.getInputStream()); while (in.available() >0) { download(); if(in.available() == 0) { Log.v("step", "succeed!!"); return; } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 获取socket上的信息 } } }.start();
private void download() { byte[] bytes = new byte[8]; // 服务器上已定义了发送一段8字节的信息,所以定义8字节 in.read(bytes);// 获取文件总大小(包括fileNameSize,fileSize) totalSize = new BigInteger(bytes); Log.v("receive", totalSize.toString());因为我一开始对tcp的socket不熟,以为要像udp、串口这样,同一时间是自能选择发送或接收,所以要把socket控制好。
其实只要用数据输入输出流取得socket的数据,socket就可以基本不用管了,一直监听一直发送都无所谓
二、数据类型问题
因为首先我要发送文件名和文件大小,需要固定字节发送,java和c++数据类型不完全一样,而且每个数据类型大小也很可能不同,所以在数据方面也花了很多时间
1.首先是电脑发文件给手机,我在C++上用的是Qt的64位的qint64,所以java上也要用相同位数的数据类型BigInteger
byte[] bytes = new byte[8]; // 服务器上已定义了发送一段8字节的信息,所以定义8字节 in.read(bytes);// 获取文件总大小(包括fileNameSize,fileSize) totalSize = new BigInteger(bytes); Log.v("receive", totalSize.toString());
2.手机发给电脑,在Android的获取文件大小的方法返回的是long,上网查了下long是8bytes,1byte8位,所以应该是64位
但是实际应用中就出现问题。
byte[] b = new byte[4]; Long totalSize = file.length() +Long.valueOf(fileName.length()+1); b = longToBytes(totalSize); out.write(b);上面是正确代码,用的是4bytes,而不是8bytes。
long转bytes用的是百度的方法,而不能用b = totalSize.toString().getBytes();
所以在C++上也不能用quint64,而要用quint32,也就是32位。
暂时先写到这里