概览
网络分层
网络分层就是将网络节点所需要的数据的发送或者转发、打包或者拆包,以及控制信息的加载或者拆出等工作。
- 物理层
该层负责比特流在节点间的传输,即负责物理传输。该层的协议与链路有关,与传输介质也有关系 - 数据链路层
该层控制网络层与物理层之间的通信,主要功能是如何在不可靠的物理线路上进行可靠的数据传输,为保证传输,从网络层接受到的数据被分割成特定可被物理层传输的帧,帧是用来移动数据的结构包,它不仅仅包括原始数据,还包括发送方和接受方的物理地址以及纠错和控制信息。其中地址包括帧将发往何处,而纠错信息和控制信息则保证帧无差错到达。如果在传输数据时,接收点检测到所传输的数据中有差错,就要通知发送方重发一帧。 - 网络层
该层决定了如何将数据从发送方路由到接收方,网络层通过综合考虑发送优先权、网络拥塞程度、服务质量以及可选路由的花费来决定从一个网络中的节点A到另一个网络节点B的最佳路径 - 传输层
传输层为两台主机上的应用程序提供了端到端的通信,网络层的协议是建立在主机到主机的通信,传输层有两个协议:TCP和UDP。 - 应用层
应用程序接收到传输层的数据后,接下来就是要进行解读。解读必须实现提供好数据格式,而应用层就是规定了应用程序的数据格式。
TCP的三次握手四次挥手
如果要理解HTTP协议,首先进行HTTP连接网络时会进行TCP三次握手,然后传输数据,之后在释放连接。
但是如果有大量的链接、关闭每次都要进行三次握手、四次挥手,会降低性能,HTTP会有一个KEEP connections的机制,可以在传输数据后仍保持链接状态,当客户端需要时可以再次获取,无需握手。
TCP的流量控制
如果发送方把数据发送的太快,接受方可能会来不及接受,这就会造成数据的丢失。所谓的流量控制就是让发送方的发送频率不要太快,让接受方来得及接收。利用滑动窗口可以很方便的在TCP连接上实现对发送方的流量控制。
TCP的拥塞控制
- 慢开始和拥塞避免
- 快重传和快恢复
HTTP协议原理
HTTP的发展:
- http0.9:只有一个命令GET,服务器只能回应HTML格式的字符串
- http1.0:增加了POST命令还有head命令。同时HTTP的请求和回应的格式除了数据部分,每次通信还需要包括头部信息,用来描述一些元数据。
- HTTP1.1:进一步完善,增加了长连接状态,在一次TCP链接中可以多次传输数据。增加了一个pipeLine,可以多次发送数据。增加了了点头部信息
- SPDY:谷歌改善了1.1提供的改进版本
- HTTP2.0:全新升级版本,所有数据以二进制传输的,同一个连接里面发送多个请求就不再按照顺序来进行一个返回处理
HTTP的优势:简单快速。灵活、无状态,无连接
HTTP的请求方式
- GET:请求获取Request-URI所表示的资源
- POST:在URI标识后面附加新的数据
- HEAD:请求获取Request-URI所标识的资源报头
- PUT:服务器存储数据
- DELETE:服务器删除数据
- TRACE:请求服务器回收送到的请求信息
- CONNECT:将连接改为感到
- OPTIONS:性能查询
PostMan是学习HTTP协议的最好工具。
OKhttp至Retrofit
public class MainActivity extends AppCompatActivity {
@BindView(R.id.show) TextView show;
@BindView(R.id.target) MaterialEditText target;
@BindView(R.id.start) Button start;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String tar=target.getText().toString();
request(tar);
}
});
}
@SuppressLint("HandlerLeak")
public Handler handler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what == 123){
show.setText((String)msg.obj);
}
};
};
public void request(String tarString) {
//步骤4:创建Retrofit对象
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fanyi.youdao.com/") // 设置 网络请求 Url
.addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
.build();
// 步骤5:创建 网络请求接口 的实例
PostRequest_Interface request = retrofit.create(PostRequest_Interface.class);
//对 发送请求 进行封装(设置需要翻译的内容)
Call<Transslation1> call = request.getCall(tarString);
//步骤6:发送网络请求(异步)
call.enqueue(new Callback<Transslation1>() {
//请求成功时回调
@Override
public void onResponse(Call<Transslation1> call, Response<Transslation1> response) {
// 步骤7:处理返回的数据结果:输出翻译的内容
System.out.println(response.body().getTranslateResult().get(0).get(0).getTgt());
Message msg=new Message();
msg.what=123;
msg.obj=response.body().getTranslateResult().get(0).get(0).getTgt();
handler.sendMessage(msg);
}
//请求失败时回调
@Override
public void onFailure(Call<Transslation1> call, Throwable throwable) {
System.out.println("请求失败");
System.out.println(throwable.getMessage());
}
});
}
public interface PostRequest_Interface {
@POST("translate?doctype=json&jsonversion=&type=&keyfrom=&model=&mid=&imei=&vendor=&screen=&ssid=&network=&abtest=")
@FormUrlEncoded
Call<Transslation1> getCall(@Field("i") String targetSentence);
//采用@Post表示Post方法进行请求(传入部分url地址)
// 采用@FormUrlEncoded注解的原因:API规定采用请求格式x-www-form-urlencoded,即表单形式
// 需要配合@Field 向服务器提交需要的字段
}
public class Transslation1{
private String type;
private int errorCode;
private int elapsedTime;
private List<List<TranslateResultBean>> translateResult;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public int getElapsedTime() {
return elapsedTime;
}
public void setElapsedTime(int elapsedTime) {
this.elapsedTime = elapsedTime;
}
public List<List<TranslateResultBean>> getTranslateResult() {
return translateResult;
}
public void setTranslateResult(List<List<TranslateResultBean>> translateResult) {
this.translateResult = translateResult;
}
public static class TranslateResultBean {
public String src;
public String tgt;
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
public String getTgt() {
return tgt;
}
public void setTgt(String tgt) {
this.tgt = tgt;
}
}
}
OkHttp基础
Okhttp的请求网络流程:
- 处理请求
当我们要请求网络的时候需要用到OkHttpCient.newCall进行execute和enqueue操作 - dispatcher任务调度
- Interceptor拦截器
- 缓存策略
- 失败重连
Retrofit
一开始的小例子就是通过Rerofit实现的简单的翻译,利用的是开源的翻译api,Retrofit是Square开发的针对Android请求的框架,Retrofit底层是基于Okhttp实现的,提供注解的方式来使用。Retrofit的注解分为三大类:HTTP请求方法注解、标记类方法注解和参数类注解