到目前从事安卓应用开发的经历中,有使用到和网络连接相关的时候有三处:

一是电话本客服号码内置时,客服号码信息需要支持在线更新功能,当时有做应用与服务器连接取数据,然后判断是否要更新;

二是维护下载管理模块的时候,有分析过无法下载的问题时有了解过;

三是自己开发了一个自动下载谷歌play排名前1000应用的工具时,设计到下载功能;

想来这三处应该用到的都是Android里面自带的HttpUrlConnection工具类提供的功能,刚刚查了一下,这个还是java自带的。

https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html

 

从网上资料得知,在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。这个是由于各个不同时期两者存在的bug和受重视程度不同有关,历史的车轮滚滚向前,版本迭代更新,目前肯定就是都乐于使用HttpUrlConnection 了。

 

HttpURLconnection是基于http协议的,支持get,post,put,delete等各种请求方式,最常用的就是get和post。但是我的代码中没有对此进行声明处理,例如电话本中下载客服号码信息文件的代码如下:

/**
* http connection
*
* return value: if failed :null
* succeed : inputstream
*/
public InputStream getInputStream(String urlStr) throws IOException {
InputStream is = null;
URL mUrl = null;
int mContentLength = 0;
try {
mUrl = new URL(urlStr);

Log.d(TAG,"[getInputStream]urlStr= "+urlStr+" ,url= "+mUrl.toString());

HttpURLConnection urlConn = (HttpURLConnection) mUrl.openConnection(); // 通过URL获取连接对象,此后没有设置请求方式是否为get还是post,默认就是get
Log.d(TAG,"[getInputStream] urlConn="+urlConn);
//set timeout time
urlConn.setConnectTimeout(10000); //设置连接超时时间
urlConn.setReadTimeout(10000);//设置读取超时时间
urlConn.setDoInput(true);// 允许写入,因为我这边是要从服务端获取,所以要输入,这个默认也是true.  而setDoOutput,设置是否要输出,默认false


is = urlConn.getInputStream(); //没有使用connect连接方法,直接获取数据流了,也没有出现问题,但是注意使用connect之后,就不要再设置参数了
Log.d(TAG,"[getInputStream] is="+is);
mContentLength = urlConn.getContentLength();  //如果使用了压缩Accept-Encoding: gzip需要注意这个长度是压缩长度。
Log.d(TAG,"mContentLength="+mContentLength);

if(mContentLength <= 0){
Log.w(TAG,"can not get file size");
return null;
}

} catch (MalformedURLException e) {
Log.e(TAG,"MalformedURLException");
e.printStackTrace();
}
catch(NetworkOnMainThreadException e){
Log.d(TAG,"NetworkOnMainThreadException ");
e.printStackTrace();
}
catch(UnknownHostException e){
Log.d(TAG,"UnknownHostException ");
e.printStackTrace();
}
catch(Exception e){
Log.d(TAG,"Exception ");
e.printStackTrace();
}
finally{
Log.d(TAG,"getInputStream over");
}

return is;
}

 

 

---------------在自动下载谷歌play应用的工具代码中,关于网络连接部分代码如下-----------------

/*
* url: download link
* name: the download apk name in the PC
* oldName: apk package name
*/
public static String download(String id ,String url, String name,String oldName){
URL e = null;
File file;
URLConnection uc;
int mFileSize = -1;
System.out.println("-----download id="+id+" url="+url+" name="+name+" oldName="+oldName);
try {
e = new URL(url);
uc = e.openConnection();
uc.addRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");  // 这里主要是设置UA信息,不然有可能是下载不了
uc.connect();

file = new File(downpath + name);

//avoid download the same file again
if(file.exists()){
return STATUS_SUCCEED;
}

//get the download file size by 'content-length' field
mFileSize = uc.getContentLength();

InputStream is = uc.getInputStream();

System.out.println("download begin to copy stream....");
long start = System.currentTimeMillis();
//copy the stream to local storage
FileUtils.copyInputStreamToFile(is,file);
long end = System.currentTimeMillis();

System.out.println("download copy stream over!! spent time: "+(end-start)/1000+" s");
//record the result
if(mFileSize != -1){
//succeed , do nothing
}else{
//delete it if failed
if(file.isFile() && file.exists()) {
file.delete();
}

return STATUS_FAIL;
}
System.out.println(name+" "+mFileSize);
} catch (Exception var) {

System.out.println(" download Exception");
var.printStackTrace();

file = new File(downpath +name);
if(file.isFile() && file.exists()) {
file.delete();
}

return STATUS_EXCEPTION;
}

return STATUS_SUCCEED;
}

 

 

 

----------------关于在维护下载管理模块是对于http网路连接的一点认识-----------------

Gamil 和 雅虎邮箱在数据流量的情况下不能下载附件问题,当时分析到的是雅虎服务器没有给出Content-length 域的值,导致代码无法判断文件大小而做的一个

禁止下载的处理;另外在android原生代码里面4.4的逻辑是通过判断Content-length 还有 编码类型来看是否继续下载,5.1版本之后又增加了判断是否为持久连接的逻辑,所以从这一系列问题中可以看出,网络连接里面有很多细节事项参数需要注意:

1、文件大小 content-length

2、编码类型 encodetype,分块传输编码(Chunked transfer encoding)可以用来传输大文件,不会告诉content-length大小

3、连接类型: 持久连接 和 非持久连接 ,HTTP/1.0使用非持久连接,HTTP/1.1默认使用持久连接,事物处理结束后,不关闭TCP连接。

1)HTTP/1.0 + keep-alive 连接, 即默认为非持久,如果要需要发送请求时增加 Connection:Keep-Alive

2) HTTP/1.1 + persistent 连接, 即默认为持久连接,如果需要关闭需要在最后一条请求中发送一个Connection:close请求首部

 

以上只是我在实际工作中碰到的一些场景知识的总结,实际HTTPUrlConnection的使用场景更多,除了我这边用到的下载文件,还有上传参数,上传文件等,具体可以参考: https://blog.csdn.net/fightingXia/article/details/71775516

 

 

 

-----------------关于socket  tcp/ip  http 的一点了解--------------------

socket套接字包含了五个信息:使用协议类型,源地址IP , 源端口, 目标地址IP, 目标地址端口, 是实现TCP/IP协议栈的一种工具,提供接口,方便调用;

TCP/IP 是传输层的协议,基于网络层IP协议,定义了数据如何传输,里面有三次握手规则来确保TCP连接的建立:

1、客户端发送SYNC同步状态给服务端, 进入同步发送状态;

2、服务端收到SYNC同步信号,进行ACK确认+1处理,然后发送SYNC+ACK给客户端,进入同步接受状态;

3、客服端接受到SYNC+ACK之后,进行确认ACK+1,发送给服务端;

然后连着进入连接建立状态, 之所以是三次握手是从稳定性和效率两方面来考虑的。

 

HTTP协议是应用层协议,即数据如何包装解析呈现给应用,每次请求都需要服务器响应,是一种短连接。