社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
是服务端绑定port端口,调accept()监听等待客户端连接,它返回一个连接队列中的一个socket。
创建客户端连接主机的socket流,其中InetAddress是用来记录主机的类,port指定端口。
socket和servletSocket的交互如下图所示:
Android中主要提供了两种方式来进行HTTP操作,HttpURLConnection和HttpClient。这两种方式都支持HTTPS协议、以流的形式进行上传和下载、配置超时时间、IPv6、以及连接池等功能。
获取HttpURLConnection的实例:
URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
设置一下HTTP请求所使用的方法,常用的方法主要有两个GET和POST,GET表示希望从服务器那里获取数据,而POST则表示希望提交数据给服务器:
connection.setRequestMethod("GET");
网络定制:比如设置链接超时,读取超时的毫秒数,以及服务器希望得到的一些消息头等。
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
调用getInputStream()方法获取到服务器返回的输入流:
InputStream in = connection.getInputStream();
调用disconnect()方法可以将HTTP链接关闭:
connection.disconnect();
流的读取:
reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null){
response.append(line);
}
showResponse(response.toString());
//reader.close();记得最后关闭
包含HttpGet和HttpPost类。Android6.0开始过时,官方推荐HttpURLConnection。
HttpClient是Apache开源组织提供的HTTP网络访问接口(一个开源的项目),是一个简单的HTTP客户端(并不是浏览器),可以发送HTTP请求,接受HTTP响应。但是不会缓存服务器的响应,不能执行HTTP页面中签入嵌入的JS代码,自然也不会对页面内容进行任何解析、处理,这些都是需要开发人员来完成的。
现在Android已经成功集成了HttpClient,所以开发人员在Android项目中可以直接使用HttpClient来想Web站点提交请求以及接受响应,如果使用其他的Java项目,需要引入进相应的Jar包。
HttpClient其实是一个interface类型,HttpClient封装了对象需要执行的Http请求、身份验证、连接管理和其它特性。既然HttpClient是一个接口,因此无法创建它的实例。从文档上看,HttpClient有三个已知的实现类分别是:AbstractHttpClient, AndroidHttpClient, DefaultHttpClient,会发现有一个专门为Android应用准备的实现类AndroidHttpClient,当然使用常规的DefaultHttpClient也可以实现功能。
从两个类包所有在位置就可以看出区别,AndroidHttpClient定义在android.net.http.AndroidHttpClient包下,属于Android原生的http访问,而DefaultHttpClient定义在org.apache.http.impl.client.DefaultHttpClient包下,属于对apche项目的支持。而AndroidHttpClient没有公开的构造函数,只能通过静态方法newInstance()方法来获得AndroidHttpClient对象。
i>创建代表客户端的HttpClient对象。HttpClient client
ii>创建代表请求的对象。
HttpGet get,HttpPost post
注:对于发送请求的参数,GET和POST使用的方式不同,GET方式可以使用拼接字符串的方式,把参数拼接在URL结尾;POST方式需要使用setEntity(HttpEntity entity)方法来设置请求参数。
iii>调用HttpClient对象的execute(HttpUriRequest request)发送请求,执行该方法后,将获得服务器返回的HttpResponse对象。服务器发还给我们的数据就在这个HttpResponse相应当中。
HttpResponse response = client.execute(post)
HttpEntity entity = response.getEntity()
得到数据流:
InputStream inputStream = entity.getContent();
最后关闭过期连接。
iv>检查相应状态是否正常。服务器发给客户端的相应,有一个相应码:相应码为200,正常;相应码为404,客户端错误;相应码为505,服务器端错误。
v>获得相应对象当中的数据
GET是从服务器上获取数据,POST是向服务器传送数据。
在客户端,GET方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放在HTML HEADER内提交。
对于GET方式,服务器端用Request.QueryString获取变量的值,对于POST方式,服务器用Request.Form获取提交的数据。
GET方式提交的数据不能大于2KB(主要是URL长度限制),而POST则没有此限制。
安全性问题。正如2中提到,使用GET的时候,参数会显示在地址栏上,而POST不会。所以,如果这些数据是中文数据而且是非敏感数据,那么使用GET;如果用户输入的数据不是中文字符而且包含敏感数据,那么还是使用POST为好。
1、以HTML代码内容返回。
2、以XML字符串的形式返回,在以后的android开发中这种形式返回数据比较多。
3、以JSON对象形式返回,在网络流量上考虑JSON要比XML方式要好一些,便于解析。
在Android当中,一般使用xml和Json数据解析。
网络请求框架,可通过第三方依赖导入。
包括Get 请求、Post 请求、上传下载文件、上传下载图片等功能。
网络请求框架,可通过第三方依赖导入。
无论是socket连接还是http连接,不应该在主线程中进行,否则会报错:android.os.NetworkOnMainThreadException。
正确的做法是:在异步任务或者新开子线程用于连接。
public class NetWork {
/**
* 检查当前网络是否可用
*
* @param context
* @return
*/
public static boolean isNetWork(Context context) {
if (context != null) {
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo != null) {
return mNetworkInfo.isAvailable();
}
}
return false;
}
}
public class PingIpAddr {
/**
* ping网络,ping通返回true,不通返回false
* @param ipAddress = "74.125.47.104"
* @return
*/
public static final boolean pingIpAddr(String ipAddress) {
try {
/**-c 是指ping的次数 3是指ping 3次 ,-w 100 以秒为单位指定超时间隔,是指超时时间为100秒*/
if (null == ipAddress || ipAddress.equals("")) {
return false;
}
Process p = Runtime.getRuntime().exec("ping -c 1 -w 3 " + ipAddress);
if (null != p) {
int status = p.waitFor();
if (0 == status) {
return true;
}
}
} catch (IOException e) {
LogUtil.i("Log", "PingIpAddr->Fail: IOException->" + e.getMessage());
} catch (InterruptedException e) {
LogUtil.i("Log", "PingIpAddr->Fail: InterruptedException->" + e.getMessage());
}
return false;
}
}
提供与联网有关的类,包括流、数据包套接字(socket)、Internet协议、常见Http处理等。比如:创建URL,以及URLConnection/HttpURLConnection对象、设置链接参数、链接到服务器、向服务器写数据、从服务器读取数据等通信。这些在Java网络编程中均有涉及,我们看一个简单的socket编程,实现服务器回发客户端信息。
是一个开源项目,功能更加完善,为客户端的Http编程提供高效、最新、功能丰富的工具包支持。
常常使用此包下的类进行Android特有的网络编程,如:访问WiFi,访问Android联网信息,邮件等功能。
http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。http的连接很简单,是无状态的。HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网站服务器的身份 认证,保护交换数据的隐私与完整性。
SSL(安全套接层,secure sockets layer)
TLS(传输层安全,transport layer security),是SSL的继任者。
安全层其实就是在明文的上层和TCP层之间加上一层加密,这样就保证上层信息传输的安全。
注:TLS是SSL的升级替代版,具体发展历史可以参考传输层安全性协议。
HTTP与HTTPS在写法上的区别也是前缀的不同,客户端处理的方式也不同,具体说来:
如果URL的协议是HTTP,则客户端会打开一条到服务端端口80(默认)的连接,并向其发送老的HTTP请求。
如果URL的协议是HTTPS,则客户端会打开一条到服务端端口443(默认)的连接,然后与服务器握手,以二进制格式与服务器交换一些SSL的安全参数,附上加密的 HTTP请求。
所以HTTPS比HTTP多了一层与SSL的连接,这也就是客户端与服务端SSL握手的过程,整个过程主要完成以下工作:
SSL/TSL的常见开源实现是OpenSSL,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。 更多源于OpenSSL的技术细节可以参考OpenSSL。
HTTP的缓存机制也是依赖于请求和响应header里的参数类实现的,最终响应式从缓存中去,还是从服务端重新拉取,HTTP的缓存机制的流程如下所示:
HTTP的缓存可以分为两种:
①强制缓存
需要服务端参与判断是否继续使用缓存,当客户端第一次请求数据是,服务端返回了缓存的过期时间(Expires与Cache-Control),没有过期就可以继续使用缓存,否则则不适用,无需再向服务端询问。
②对比缓存
需要服务端参与判断是否继续使用缓存,当客户端第一次请求数据时,服务端会将缓存标识(Last-Modified/If-Modified-Since与Etag/If-None-Match)与数据一起返回给客户端,客户端将两者都备份到缓存中 ,再次请求数据时,客户端将上次备份的缓存 标识发送给服务端,服务端根据缓存标识进行判断,如果返回304,则表示通知客户端可以继续使用缓存。
强制缓存优先于对比缓存。
上面提到强制缓存使用的的两个标识:
private: 客户端可以缓存。
public: 客户端和代理服务器都可缓存。
max-age=xxx: 缓存的内容将在 xxx 秒后失效
no-cache: 需要使用对比缓存来验证缓存数据。
no-store: 所有内容都不会缓存,强制缓存,对比缓存都不会触发。
我们再来看看对比缓存的两个标识:
If-Modified-Since: Tue, 12 Jan 2016 09:31:27 GMT
服务端接收到客户端发来的资源修改时间,与自己当前的资源修改时间进行对比,如果自己的资源修改时间大于客户端发来的资源修改时间,则说明资源做过修改, 则返回200表示需要重新请求资源,否则返回304表示资源没有被修改,可以继续使用缓存。
上面是一种时间戳标记资源是否修改的方法,还有一种资源标识码ETag的方式来标记是否修改,如果标识码发生改变,则说明资源已经被修改,ETag优先级高于Last-Modified。
If-None-Match:“5694c7ef-24dc”
服务端接收到客户端发来的资源标识码,则会与自己当前的资源吗进行比较,如果不同,则说明资源已经被修改,则返回200,如果相同则说明资源没有被修改,返回 304,客户端可以继续使用缓存。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!