OSI七层模型 TCP/IP四层模型
HTTP协议
HttpClient HttpURLConnection
TCP协议 UDP协议
Socket实现TCP通信
Socket实现UDP通信
为了使不通类型的计算机之间可以相互通信,国际化标准组织提出了OSI七层网络模型,从下到上分别是:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。但是OSI七层网络模型仅仅用于实验室,并没有真正的使用它,实际的环境中用的是TCP/IP四层模型,TCP/IP四层网络模型包括:链路层、网络层、传输层、应用层。
链路层:
处理数据在物理介质(比如以太网)上的传输,网络驱动程序运行在该层,网络驱动程序隐藏了物理媒介的电气特性,为上层提供了统一的接口。
主要协议:
ARP协议:地址解析协议,根据IP地址获取物理地址。
RARP协议:逆地址解析协议,根据物理地址获取IP地址。
网络层:
网络层是TCP/IP模型的核心层,网络层主要是确定主机的通信路径,实现数据包的选路和转发。
主要协议:
IP协议(Internet Protocol):根据数据包目的IP地址选择如果投递该数据包。寻找合适的转发路由器,将该数据包交给路由器转发。
ICMP协议(Internet Control Message Protocol):主要用于检测网络的连接状态。如ping命令就是ICMP协议的应用。
传输层:
为两台主机中的应用程序提供端到端的通信,只关心通信两端的信息,不关心数据包的传输过程。负责数据的转发、链路超时重连等。
主要协议:
TCP(Transmission Control Protocol)协议: 传输控制协议,为应用层提供可靠的、面向连接的、基于流的服务。
UDP(User Datagram Protocol)协议:用户数据报协议,为应用层提供不可靠的、无连接的、基于数据报的服务。
应用层:
基于其他三层网络协议,实现处理一些应用程序的逻辑和功能,如文件传输等。
主要协议:
HTTP协议:超文本传输协议,基于TCP,使用80或者8080端口。
FTP协议:文件传输协议,基于TCP,使用20或者21端口。
DNS(Domain Name Service):域名服务。
HTTP协议:
HTTP(Hypertext Transfer Protocol),基于TCP协议之上的请求/响应式协议,HTTP指定客服端与服务器如何建立连接、客服端如何从服务器获取数据、服务器如何响应请求、以及如何关闭连接等。
请求报文:
请求行组成:请求方法+空格+请求地址+http协议版本号+回车符+换行符
HTTP请求方法有8种:
GET:请求获取Request-URI所标识的资源
POST:在Request-URI所标识的资源后附加新的数据
HEAD:请求获取由Request-URI所标识的资源的响应消息报头
PUT: 请求server存储一个资源。并用Request-URI作为其标识
DELETE :请求server删除Request-URI所标识的资源
TRACE : 请求server回送收到的请求信息。主要用于測试或诊断
CONNECT: HTTP/1.1协议中预留给能够将连接改为管道方式的代理server。
OPTIONS :请求查询server的性能。或者查询与资源相关的选项和需求
请求行后面是0个或多个请求报头。请求报头后面还有不可少的空行,如果是POST请求,空行后面还有请求数据。
响应报文:
状态行组成:http协议版本号+空格+响应状态代码。
响应状态代码:
100~199:指示信息,表示请求已接收,继续处理
200~299:请求成功。表示请求已被成功接收、理解、接受
300~399:重定向,要完毕请求必须进行更进一步的操作
400~499:client错误。请求有语法错误或请求无法实现
500~599:server端错误,server未能实现合法的请求
常见的响应状态代码:
200 OK:client请求成功
400 Bad Request:client请求有语法错误,不能被server所理解
401 Unauthorized:请求未经授权,这个状态代码必须和WWW-- - - Authenticate报头域一起使用
403 Forbidden:server收到请求。可是拒绝提供服务
404 :请求资源不存在
500 Internal Server Error:server发生不可预期的错误
503 Server Unavailable:server当前不能处理client的请求。一段时间后可能恢复正常
Android中为我们提供了两个实现HTTP请求的类:HttpClient和HttpUrlConnection。
HttpClient:HttpClient是Apache提供的一个开源项目,HttpClient是一个接口,我们不能直接创建他的实例,可以通过它的实现类DefaultHttpClient或者AndroidHttpClient创建HttpClient对象。一个HttpClient请求大致分为以下几步:
1、创建HttpClient对象
2、创建请求对象:Get请求创建HttpGet对象,Post请求创建HttpPost对象。
3、调用HttpClient对象得execute方法获取返回的HttpResponse对象。
4、通过HttpResponse获取响应数据。
HttpClient发送Get请求:
public static void httpClientGet(String url) {
try {
//创建HttpClient对象
HttpClient httpClient = new DefaultHttpClient();
//创建HttpGet对象
HttpGet httpGet = new HttpGet(url);
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
HttpConnectionParams.setSoTimeout(params, 10 * 1000);
httpGet.setParams(params);
//调用HttpClient对象的execute方法 获取返回的HttpResponse
HttpResponse response = httpClient.execute(httpGet);
//解析对应数据
int state = response.getStatusLine().getStatusCode();
Log.i(TAG, "httpClientGet-->state:" + state);
if (state == 200) {
HttpEntity entity = response.getEntity();
String content = EntityUtils.toString(entity,"utf-8");
Log.i(TAG, "content-->" + content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
HttpClient发送POST请求:
public static void httpClientPost(String url, JSONObject jsonObject) {
//构造消息实体
try {
HttpPost httpPost = null;
HttpClient httpClient = new DefaultHttpClient();
httpPost = new HttpPost(url);
//设置请求超时
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
HttpConnectionParams.setSoTimeout(params, 10 * 1000);
httpPost.setParams(params);
//设置请求超时
// httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10 * 1000);
// httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 10 * 1000);
//构造消息头
httpPost.setHeader("Content-type", "application/json; charset=utf-8");
httpPost.setHeader("Connection", "Close");
//构造消息实体
StringEntity entity = new StringEntity(jsonObject.toString());
entity.setContentEncoding("UTF-8");
//发送数据
entity.setContentType("application/json");
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
int state = response.getStatusLine().getStatusCode();
Log.i(TAG, "httpClientPost-->state:" + state);
if (200 == state) {
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
Log.i(TAG, "name:" + header.getName() + ",value:" + header.getValue());
}
HttpEntity contentEntity = response.getEntity();
String content = EntityUtils.toString(contentEntity, "utf-8");
Log.i(TAG, "content-->" + content);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
HttpUrlConnection:一个轻量级的HTTP客服端,API简单,相对扩展容易,HttpUrlConnection的压缩和缓存机制可以有效的减少网络访问的流量。在Android2.3以前HttpUrlConnection存在一些BUG(如:对一个可读的InputStream调用close()方法时可能会导致连接池失效)网络访问基本用的是HttpClient,在Android2.3及以上HttpUrlConnection则是最好的选择,Google在Android6.0完全移除了HttpClient。
HttpUrlConnection发送GET请求:
public static void httpUrlConnectionGet(String connectUrl) {
try {
//获取URL对象
URL url = new URL(connectUrl);
//获取HttpURLConnection对象
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//设置请求方式
urlConnection.setRequestMethod("GET");
//设置连接超时和读取超时
urlConnection.setConnectTimeout(10 * 1000);
urlConnection.setReadTimeout(10 * 1000);
//以上配置需要在调用connect()方法前调用,之后调用不起作用。
//建立连接 注意:这里仅仅是建立连接 当我们调用getInputStream()的时候 也会调用connect()方法
urlConnection.connect();
//处理数据
int responseCode = urlConnection.getResponseCode();
Log.i(TAG, "responseCode:" + responseCode);
if (responseCode == 200) {
InputStream is = urlConnection.getInputStream();
StringBuilder builder = new StringBuilder();
InputStreamReader reader = new InputStreamReader(is);
int len = 0;
char[] chars = new char[1024];
while ((len = reader.read(chars)) != -1) {
builder.append(new String(chars, 0, len));
}
Log.i(TAG, "content:" + builder.toString());
is.close();
reader.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
HttpUrlConnection发送POST请求:post请求主要就是获取HttpUrlConnection的输出流getOutputStream(),之后往输出流中写入需要发送到服务端的数据。
public static void httpUrlConnectionPost(String url, String body) {
try {
URL postUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection();
connection.setRequestMethod("POST");
connection.setConnectTimeout(10 * 1000);
connection.setReadTimeout(10 * 1000);
//设置是否向HttpURLConnection 输出,默认为false
connection.setDoOutput(true);
//设置是否从HttpURLConnection读入,默认伟true
connection.setDoInput(true);
//post请求不能使用缓存
connection.setUseCaches(false);
//设置传送的内容类型是可序列号的Java对象
//如果不设置 当服务端默认不是这种类型时会抛出异常
connection.setRequestProperty("Content-type", "application/x-java-serialized-object");
connection.connect();
//获取HttpURLConnection的输出流
OutputStream os = connection.getOutputStream();
//向输出流中写入数据
BufferedWriter br = new BufferedWriter(new OutputStreamWriter(os));
br.write(body);
br.close();
//处理返回结果
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK){
InputStream is = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(is);
StringBuilder builder = new StringBuilder();
int len = 0;
char[] chars = new char[1024];
while ((len = reader.read(chars)) != -1){
builder.append(new String(chars,0,len));
}
Log.i(TAG, "content:" + builder.toString());
is.close();
reader.close();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}