OSI七層模型介紹社裆,TCP/IP模型介紹,HTTP協(xié)議格式介紹
OSI七層模型
應用層------可見的終端(瀏覽器)
表示層------計算機識別的信息轉變人可以識別的信息
回話層------傳輸端口和接受端口的建立回話
傳輸層------傳輸數(shù)據的協(xié)議與端口
網絡層------IP地址
數(shù)據鏈路層------交換機傳輸
物理層------具體物理設備
TCP/IP模型?
應用層----http https REST REMT
傳輸層----Socket
應用層
主機至網絡層
HTTP GET Request
發(fā)起請求:1.請求頭之請求行 2.? ? 請求頭之請求屬性集
HTTP POST Request
發(fā)起請求:1.請求頭之請求行? 2. 請求頭之請求屬性集? 3.請求體長度 4.請求的類型
OKHttp主線流程的源碼解讀
OKHttp的使用:
OKHttpClient------Request------newCall 執(zhí)行RealCall.enqueue(){不能重復執(zhí)行}------
Dispatcher.enqueue(AsyncCall:if先加入運行隊列攒射,執(zhí)行異步任務 else 直接加入等待隊列)------AsyncCall.excute()區(qū)分責任劃分判斷是用戶導致還是OKHttp導致的,責任鏈模式,多個攔截器,返回response别渔。
OKHttp源碼解讀之線程池詳解
線程池的作用就是避免重復創(chuàng)建和銷毀線程耗費內存
ThreadPoolExecutorexecutor=new ThreadPoolExecutor(0,Integer.MAX_VALUE,60, TimeUnit.MILLISECONDS,new LinkedBlockingDeque());
參數(shù)一:corePoolSize 核心線程數(shù)
參數(shù)二:maximumPoolSize 最大線程數(shù)
參數(shù)三/四:時間數(shù)值 keepAliveTime? ?單位unit 時分秒
? ? ? ? ? ? ? ? ? ? 正在執(zhí)行的任務數(shù)量>corePoolSize---->參數(shù)三、四才會起作用
? ? ? ? ? ? ? ? ? ? 任務執(zhí)行完畢后惧互,閑置超過參數(shù)三、四設置的時間喇伯,才會回收線程喊儡,在這段時間以內就會復用線程。
參數(shù)五:workQueue隊列 會把超出的任務加入隊列稻据,緩存起來
OkHttp里面的線程池:
public synchronized ExecutorServiceexecutorService() {
if (executorService ==null) {
executorService =new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
? ? ? ? new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
? }
return executorService;
}
有源碼可知:OkHttp里面的線程池采用的是緩存策略艾猜,
OkHttp里面線程池,采用的是緩存方案+線程工廠+非守護線程
將核心線程設為0捻悯,只要runnable>1匆赃,60秒之內就會復用線程,超過60秒回收線程今缚。
OKHttp源碼閱讀之構建者模式/責任鏈模式
構建著模式:鏈式編程結構清晰(方法返回client本身)算柳,通過Builder來實現(xiàn)參數(shù)的復制
責任鏈模式:將不同的模塊分塊,集成共同的接口姓言,設置一個manager也集成共同的接口瞬项,將不同的模塊添加到集合中蔗蹋,通過重寫共同接口的方法,達到在集合中不斷執(zhí)行不同模塊的功能囱淋,如果不符合條件就停止執(zhí)行猪杭。
OKHttp 手寫實現(xiàn)之整體框架搭建
根據OKHttp的源碼創(chuàng)建自己的OkHttpClient2??Request2?Call2??CallBack2.....
public void uesMyOkHttp(View view) {
????OkHttpClient2 okHttpClient2 =new OkHttpClient2.Builder().build();
? ? Request2 request2 =new Request2.Builder().url("https://www.baidu.com").build();
? ? Call2 call = okHttpClient2.newCall(request2);
? ? call.enqueue(new CallBack2() {
????@Override
? ? ? ? public void onFailure(Call2 call, IOException e) {
????Log.e("eeeeeee",e.getMessage());
? ? ? ? }
@Override
? ? ? ? public void onResponse(Call2 call, Response2 response)throws IOException {
Log.e("eeeeeee",response.getBody());
? ? ? ? }
});
}
OkHttpClient2??Request2一樣,都是采用創(chuàng)建者模式妥衣,鏈式編程可以傳入自定義的參數(shù)皂吮、
public class OkHttpClient2 {
private Dispacher2dispacher2;
? ? private boolean isCancle;
? ? private Stringurl;
? ? private int recount;
? ? public int getRecount() {
return recount;
? ? }
public OkHttpClient2() {
this(new Builder());
? ? }
public OkHttpClient2(Builder builder) {
this.dispacher2 = builder.dispacher2;
? ? ? ? this.isCancle = builder.isCancle;
? ? ? ? this.url = builder.url;
? ? ? ? this.recount=builder.recount;
? ? }
public boolean getCanle() {
return isCancle;
? ? }
public static final class Builder {
private Stringurl;
? ? ? ? private Dispacher2dispacher2;
? ? ? ? private boolean isCancle;
? ? ? ? int recount =3;//默認重試3次
? ? ? ? public Builder() {
dispacher2 =new Dispacher2();
? ? ? ? }
public OkHttpClient2build() {
return new OkHttpClient2(this);
? ? ? ? }
public BuildersetCount(int recount) {
this.recount = recount;
return this;
? ? ? ? }
public Buildercancle() {
isCancle =true;
return this;
? ? ? ? }
public Builderdispacher(Dispacher2 dispacher2) {
this.dispacher2 = dispacher2;
return this;
? ? ? ? }
public Builderurl(String url) {
this.url = url;
return this;
? ? ? ? }
}
public Call2newCall(Request2 request2) {
return new RealCall2(request2, this);
? ? }
public Dispacher2dispacher() {
return dispacher2;
? ? }
}
public class Request2 {
public static final StringGET ="GET";
? ? public static final StringPOST ="POST";
? ? private Stringurl;
? ? public StringgetUrl() {
return url;
? ? }
public StringgetRequestMethod() {
return requestMethod;
? ? }
public MapgetmHeadList() {
return mHeadList;
? ? }
private StringrequestMethod =GET;
? ? private MapmHeadList =new HashMap<>();
? ? public Request2() {
this(new Builder());
? ? }
public Request2(Builder builder) {
this.url = builder.url;
? ? ? ? this.requestMethod = builder.requestMethod;
? ? ? ? this.mHeadList = builder.mHeadList;
? ? }
public static final class Builder {
private Stringurl;
? ? ? ? private StringrequestMethod =GET;
? ? ? ? private MapmHeadList =new HashMap<>();
? ? ? ? public Request2build() {
return new Request2(this);
? ? ? ? }
public Builderget() {
requestMethod =GET;
return this;
? ? ? ? }
public Builderpost() {
requestMethod =POST;
return this;
? ? ? ? }
public BuilderaddHead(String key, String value) {
mHeadList.put(key, value);
return this;
? ? ? ? }
public Builderurl(String url) {
this.url = url;
return this;
? ? ? ? }
}
}
定義一個接口Call2
public interface Call2 {
void enqueue(CallBack2 responseCallback);
}
定義一個RealCall實現(xiàn)Call2
public class RealCall2implements Call2 {
private boolean excuted;
? ? private Request2request2;
? ? private OkHttpClient2okHttpClient2;
? ? public boolean isExcuted() {
return excuted;
? ? }
public Request2getRequest2() {
return request2;
? ? }
public OkHttpClient2getOkHttpClient2() {
return okHttpClient2;
? ? }
public RealCall2(Request2 request2, OkHttpClient2 okHttpClient2) {
this.request2 = request2;
? ? ? ? this.okHttpClient2 = okHttpClient2;
? ? }
@Override
? ? public void enqueue(CallBack2 responseCallback) {
synchronized (this) {
if (excuted) {
excuted =true;
? ? ? ? ? ? ? ? throw new IllegalArgumentException("Already Executed");
? ? ? ? ? ? }
}
okHttpClient2.dispacher().enqueue(new AsyncCall2(responseCallback));
? ? }
public final class AsyncCall2implements Runnable {
private CallBack2callBack2;
? ? ? ? public Request2getRequest2() {
return RealCall2.this.request2;
? ? ? ? }
public AsyncCall2(CallBack2 callBack2) {
this.callBack2 = callBack2;
? ? ? ? }
@Override
? ? ? ? public void run() {
boolean signalledCallback =false;
? ? ? ? ? ? try {
Response2 response = getResponseWithInterceptorChain();
? ? ? ? ? ? ? ? if (okHttpClient2.getCanle()) {
signalledCallback =true;
? ? ? ? ? ? ? ? ? ? callBack2.onFailure(RealCall2.this, new IOException("用戶取消了 請求"));
? ? ? ? ? ? ? ? }else {
signalledCallback =true;
? ? ? ? ? ? ? ? ? ? callBack2.onResponse(RealCall2.this, response);
? ? ? ? ? ? ? ? }
}catch (IOException e) {
//責任的劃分
? ? ? ? ? ? ? ? if (signalledCallback) {//用戶的操作
? ? ? ? ? ? ? ? ? ? System.out.println("用戶再使用過程中? 出錯了");
? ? ? ? ? ? ? ? }else {
callBack2.onFailure(RealCall2.this, new IOException("OKHttp getResponseWithInterceptorChain錯誤 e:" + e.toString()));
? ? ? ? ? ? ? ? }
}finally {//回收
? ? ? ? ? ? ? ? okHttpClient2.dispacher().finished(this);
? ? ? ? ? ? }
}
private Response2getResponseWithInterceptorChain()throws IOException {
Response2 response2 =new Response2();
? ? ? ? ? ? response2.setBody("流程走通");
? ? ? ? ? ? return response2;
? ? ? ? }
}
}
通過構造參數(shù)將前面的client和request傳到RealCall里面?
重寫enqueue方法,執(zhí)行dispacher里面的enqueue方法
@Override
public void enqueue(CallBack2 responseCallback) {
synchronized (this) {
if (excuted) {
excuted =true;
? ? ? ? ? ? throw new IllegalArgumentException("Already Executed");
? ? ? ? }
}
okHttpClient2.dispacher().enqueue(new AsyncCall2(responseCallback));
}
創(chuàng)建Dipacher2 在enqueue方法里面判斷是將任務添加到執(zhí)行隊列還是等待隊列税手,添加到執(zhí)行隊列后利用線程池執(zhí)行任務涮较。? ??
通過finally {//回收
? ? okHttpClient2.dispacher().finished(this);
}
將等待隊列的任務便利執(zhí)行完畢。冈止,還將run方法里面責任進行劃分狂票,明確是OK HTTP本身的責任還是使用者的責任,callBack2執(zhí)行callback熙暴,將執(zhí)行情況返回給頁面闺属,
Response2 response = getResponseWithInterceptorChain();通過責任鏈模式將response返回,詳細情況在下面手寫socket
public class Dispacher2 {
private int maxRequests =64;//同時訪問任務周霉,最大數(shù)量是64
? ? private int maxRequestsPerHost =5;//同時訪問同一個服務器域名掂器,最大限制
? ? private DequerunningAsyncCalls =new ArrayDeque<>();
? ? private DequereadyAsyncCalls =new ArrayDeque<>();
? ? public void enqueue(RealCall2.AsyncCall2 call) {
if (runningAsyncCalls.size()
runningAsyncCalls.add(call);//加入運行隊列
? ? ? ? ? ? executorService().execute(call);//然后再執(zhí)行
? ? ? ? }else {
readyAsyncCalls.add(call);//加入等待隊列
? ? ? ? }
}
private ExecutorexecutorService() {
ExecutorService executorService =new ThreadPoolExecutor(0, 64, 60l, TimeUnit.MILLISECONDS, new SynchronousQueue(), new ThreadFactory() {
@Override
? ? ? ? ? ? public ThreadnewThread(Runnable r) {
Thread thread =new Thread(r);
? ? ? ? ? ? ? ? thread.setName("自定義的線程。俱箱。国瓮。");
? ? ? ? ? ? ? ? thread.setDaemon(false);
? ? ? ? ? ? ? ? return thread;
? ? ? ? ? ? }
});
? ? ? ? return executorService;
? ? }
/**
* 判斷AsyncCall2中的Host,在運行的隊列中,計數(shù)狞谱,然后返回
*/
? ? private int runningCallsForHost(RealCall2.AsyncCall2 call) {
int count =0;
? ? ? ? if (runningAsyncCalls.isEmpty()) {
return 0;
? ? ? ? }
SocketRequestSever src =new SocketRequestSever();
? ? ? ? //遍歷運行隊伍里面的所有人物乃摹,取出任務host==call.host +1
? ? ? ? for (RealCall2.AsyncCall2 runningAsyncCall :runningAsyncCalls) {
if (src.getHost(runningAsyncCall.getRequest2()).equals(call.getRequest2())) {
count++;
? ? ? ? ? ? }
}
return count;
? ? }
public void finished(RealCall2.AsyncCall2 call2) {
//當前運行隊列
? ? ? ? runningAsyncCalls.remove(call2);
? ? ? ? //等待隊列為空就返回
? ? ? ? if (readyAsyncCalls.isEmpty()) {
return;
? ? ? ? }
//把等待隊列任務移動到運行隊列
? ? ? ? for (RealCall2.AsyncCall2 readyAsyncCall :readyAsyncCalls) {
readyAsyncCalls.remove(readyAsyncCall);//殺出等待隊列的任務
? ? ? ? ? ? runningAsyncCalls.add(readyAsyncCall);
? ? ? ? ? ? executorService().execute(readyAsyncCall);
? ? ? ? }
}
}
創(chuàng)建CallBack2和AsyncCall2
public interface CallBack2 {
????void onFailure(Call2 call, IOException e);
? ? void onResponse(Call2 call, Response2 response)throws IOException;
}
public final class AsyncCall2implements Runnable {
private CallBack2callBack2;
? ? ? ? public Request2getRequest2() {
return RealCall2.this.request2;
? ? ? ? }
public AsyncCall2(CallBack2 callBack2) {
this.callBack2 = callBack2;
? ? ? ? }
@Override
? ? ? ? public void run() {
boolean signalledCallback =false;
? ? ? ? ? ? try {
Response2 response = getResponseWithInterceptorChain();
? ? ? ? ? ? ? ? if (okHttpClient2.getCanle()) {
signalledCallback =true;
? ? ? ? ? ? ? ? ? ? callBack2.onFailure(RealCall2.this, new IOException("用戶取消了 請求"));
? ? ? ? ? ? ? ? }else {
signalledCallback =true;
? ? ? ? ? ? ? ? ? ? callBack2.onResponse(RealCall2.this, response);
? ? ? ? ? ? ? ? }
}catch (IOException e) {
//責任的劃分
? ? ? ? ? ? ? ? if (signalledCallback) {//用戶的操作
? ? ? ? ? ? ? ? ? ? System.out.println("用戶再使用過程中? 出錯了");
? ? ? ? ? ? ? ? }else {
callBack2.onFailure(RealCall2.this, new IOException("OKHttp getResponseWithInterceptorChain錯誤 e:" + e.toString()));
? ? ? ? ? ? ? ? }
}finally {//回收
? ? ? ? ? ? ? ? okHttpClient2.dispacher().finished(this);
? ? ? ? ? ? }
}
private Response2getResponseWithInterceptorChain()throws IOException {
Response2 response2 =new Response2();
? ? ? ? ? ? response2.setBody("流程走通");
? ? ? ? ? ? return response2;
? ? ? ? }
}
自定義攔截器
首先創(chuàng)建Interceptor2接口
public interface Interceptor2 {
Response2doNext(Chain2 chain2)throws IOException;
}
創(chuàng)建一個充實攔截器ReRequestInterceptor?
public class ReRequestInterceptor implements Interceptor2 {
@Override
? ? public Response2doNext(Chain2 chain2)throws IOException {
ChainManager chainManager = (ChainManager) chain2;
? ? ? ? RealCall2 realCall2 = chainManager.getCall2();
? ? ? ? OkHttpClient2 okHttpClient2 = realCall2.getOkHttpClient2();
? ? ? ? IOException ioException =null;
? ? ? ? if (okHttpClient2.getRecount() !=0) {
for (int i =0; i < okHttpClient2.getRecount(); i++) {
try {
Response2 response2 = chain2.getResponse(chainManager.getRequest());
? ? ? ? ? ? ? ? ? ? return response2;
? ? ? ? ? ? ? ? }catch (IOException e) {
ioException = e;
? ? ? ? ? ? ? ? }
}
}
throw ioException;
? ? }
}
創(chuàng)建Chain2接口
public interface Chain2 {
Request2getRequest();
? ? Response2getResponse(Request2 request2)throws IOException;
}
創(chuàng)建ChainManager,將攔截器存放到集合中跟衅,循環(huán)便利
public class ChainManager implements Chain2 {
private final Listinterceptors;
? ? private int index;
? ? private final Request2request2;
? ? private final RealCall2call2;
? ? public? ListgetInterceptors() {
return interceptors;
? ? }
public int getIndex() {
return index;
? ? }
public? RealCall2getCall2() {
return call2;
? ? }
public ChainManager(List interceptors, int index, Request2 request2, RealCall2 call2) {
this.interceptors = interceptors;
? ? ? ? this.index = index;
? ? ? ? this.request2 = request2;
? ? ? ? this.call2 = call2;
? ? }
@Override
? ? public Request2getRequest() {
return request2;
? ? }
@Override
? ? public Response2getResponse(Request2 request2)throws IOException {
if(index>interceptors.size())throw new AssertionError();
? ? ? ? if(interceptors.isEmpty())throw new IOException("interceptor is empty");
? ? ? ? ChainManager chainManager=new ChainManager(interceptors,index++,request2,call2);
? ? ? ? Interceptor2 interceptor=interceptors.get(index);
? ? ? ? Response2 response2=interceptor.doNext(chainManager);
? ? ? ? return response2;
? ? }
}
OKHttp 手寫實現(xiàn)之socket請求與響應
創(chuàng)建SocketRequestServer
public class SocketRequestServer {
? ? private final String K = " ";
? ? private final String VIERSION = "HTTP/1.1";
? ? private final String GRGN = "\r\n";
? ? /**
? ? * todo 通過Request對象孵睬,尋找到域名HOST
? ? * @param request2
? ? * @return
? ? */
? ? public String getHost(Request2 request2) {
? ? ? ? try {
? ? ? ? ? ? // http://restapi.amap.com/v3/weather/weatherInfo?city=110101&key=13cb58f5884f9749287abbead9c658f2
? ? ? ? ? ? URL url = new URL(request2.getUrl());
? ? ? ? ? ? return url.getHost(); // restapi.amap.com
? ? ? ? } catch (MalformedURLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return null;
? ? }
? ? /**
? ? * todo 端口
? ? * @param request2
? ? * @return
? ? */
? ? public int getPort(Request2 request2) {
? ? ? ? try {
? ? ? ? ? ? URL url = new URL(request2.getUrl());
? ? ? ? ? ? int port = url.getPort();
? ? ? ? ? ? return port == -1 ? url.getDefaultPort() : port;
? ? ? ? } catch (MalformedURLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return -1;
? ? }
? ? /**
? ? * todo 獲取請求頭的所有信息
? ? * @param request2
? ? * @return
? ? */
? ? public String getRequestHeaderAll(Request2 request2) {
? ? ? ? // 得到請求方式
? ? ? ? URL url = null;
? ? ? ? try {
? ? ? ? ? ? url = new URL(request2.getUrl());
? ? ? ? } catch (MalformedURLException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? String file = url.getFile();
? ? ? ? // TODO 拼接 請求頭 的 請求行? GET /v3/weather/weatherInfo?city=110101&key=13cb58f5884f9749287abbead9c658f2 HTTP/1.1\r\n
? ? ? ? StringBuffer stringBuffer = new StringBuffer();
? ? ? ? stringBuffer.append(request2.getRequestMethod()) // GET or POST
? ? ? ? .append(K)
? ? ? ? .append(file)
? ? ? ? .append(K)
? ? ? ? .append(VIERSION)
? ? ? ? .append(GRGN);
? ? ? ? // TODO 獲取請求集 進行拼接
? ? ? ? /**
? ? ? ? * Content-Length: 48\r\n
? ? ? ? * Host: restapi.amap.com\r\n
? ? ? ? * Content-Type: application/x-www-form-urlencoded\r\n
? ? ? ? */
? ? ? ? if (!request2.getmHeaderList().isEmpty()) {
? ? ? ? ? ? Map<String,String> mapList = request2.getmHeaderList();
? ? ? ? ? ? for (Map.Entry<String, String> entry: mapList.entrySet()) {
? ? ? ? ? ? ? ? stringBuffer.append(entry.getKey())
? ? ? ? ? ? ? ? ? ? ? ? .append(":").append(K)
? ? ? ? ? ? ? ? ? ? ? ? .append(entry.getValue())
? ? ? ? ? ? ? ? ? ? ? ? .append(GRGN);
? ? ? ? ? ? }
? ? ? ? ? ? // 拼接空行,代表下面的POST伶跷,請求體了
? ? ? ? ? ? stringBuffer.append(GRGN);
? ? ? ? }
? ? ? ? // TODO POST請求才有 請求體的拼接
? ? ? ? if ("POST".equalsIgnoreCase(request2.getRequestMethod())) {
? ? ? ? ? ? stringBuffer.append(request2.getRequestBody2().getBody()).append(GRGN);
? ? ? ? }
? ? ? ? return stringBuffer.toString();
? ? }
}
在getResponseWithInterceptorChain()里面添加
private Response2 getResponseWithInterceptorChain() throws IOException {
//? ? ? ? ? ? Response2 response2 = new Response2();
//? ? ? ? ? ? response2.setBody("流程走通....");
//? ? ? ? ? ? return response2;
? ? ? ? ? ? List<Interceptor2> interceptor2List = new ArrayList<>();
? ? ? ? ? ? interceptor2List.add(new ReRequestInterceptor()); // 重試攔截器
? ? ? ? ? ? interceptor2List.add(new RequestHeaderInterceptor()); // 請求頭攔截器
? ? ? ? ? ? interceptor2List.add(new ConnectionServerInterceptor()); // 連接服務器的攔截器
? ? ? ? ? ? ChainManager chainManager = new ChainManager(interceptor2List, 0, request2, RealCall2.this);
? ? ? ? ? ? return chainManager.getResponse(request2); // 最終返回的Response
? ? ? ? }
? ? }
url 統(tǒng)一資源定位符
url.getHost()? 域名
url.getPort()? 端口
url.getFile()? 傳輸文件
url.getProtocol()? 協(xié)議