您的位置:首页 > 理论基础 > 计算机网络

网络层架构设计与实战十四错误码和重连功能设计与实现

2018-02-07 22:17 363 查看
一、注解

1、重连和重试

在进行网络连接的时候,有可能出现网络连接出错的情况,一般的做法都是重新去尝试,网络框架也是可以对这些进行处理的,如果认为某些接口是比较重要的,可以进行一些重试。重试的话可能有一些最大的连接次数,因为它不可能是无限的重试,如果无限地重试可能导致堆栈的溢出。最大的重试次数需要开发者自己去指定,重连的功能在网络框架中如何去设计呢?可以通过annotation进行配置,然后去实现这样的功能,这样在代码上也是比较简单的。

2、定义重试的注解



3、在request中定义变量



4、在builder中创建



5、对变量进行赋值并将变量返回



6、对注解进行处理



二、异步请求网络框架

1、定义变量初始化并赋值





2、httpclient功能的主要作用主要做一个网络层框架的抽象,它的基本作用主要是提供了一些网络层的基本操作,可以在这个地方增加一些异步请求的功能。异步请求的前提是线程应该在哪儿?所以需要新增一个成员变量ExecutorService mExecutor



3、在builder中定义



4、调用设置线程池的方法



5、定义重试



6、

发生异常时进行重试处理



代码:

package com.nice;

import com.nice.convert.Convert;
import com.nice.http.HttpDns;
import com.nice.http.HttpResponse;
import com.nice.http.Request;
import com.nice.http.Response;
import com.nice.http.client.okhttp.OkHttpClient;
import com.nice.http.client.origin.OriginHttpClient;
import com.nice.utils.TypeUtils;
import com.nice.utils.Utils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.concurrent.ExecutorService;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

/**
* 高度抽象的网络层接口
* <p>主要提供升级超时、域名校验、证书认证、DNS等功能</p>
*
* @author nate
* @since 2017/10/12.
*/

public class HttpClient implements Call {

private static boolean OK_HTTP_REQUEST = Utils.isExist("okhttp3.OkHttpClient");

private int mWriteTimeOut;
private int mReaderTimeOut;
private int mConnectTimeOut;
private SSLSocketFactory mSSLSocketFactory;
private HostnameVerifier mHostnameVerifier;
private Call mRealHttpClient;
private HttpDns mHttpDns;
private Request mRequest;
private Callback mCallback;
private ExecutorService mExecutor;
private List<Convert> mConverts;
private int mRetryCount;

public HttpClient(Builder builder) {
mWriteTimeOut = builder.mWriteTimeOut;
mReaderTimeOut = builder.mReaderTimeOut;
mConnectTimeOut = builder.mConnectTimeOut;
mSSLSocketFactory = builder.mSSLSocketFactory;
mHostnameVerifier = builder.mHostnameVerifier;
mHttpDns = builder.mHttpDns;
mExecutor = builder.mExecutor;
mConverts = builder.mConverts;
}

public HttpDns getHttpDns() {
return mHttpDns;
}

public int getReaderTimeOut() {
return mReaderTimeOut;
}

public int getConnectionTimeOut() {
return mConnectTimeOut;
}

public int getWriteTimeOut() {
return mWriteTimeOut;
}

public SSLSocketFactory getSSLSocketFactory() {
return mSSLSocketFactory;
}

public HostnameVerifier getHostnameVerifier() {
return mHostnameVerifier;
}

private boolean canRetry() {
return mRetryCount < mRequest.getRetryCount();
}

private void retry() {
if (mCallback != null && mRequest != null) {
mRetryCount++;
System.out.println("重试第" + mRetryCount + "次");
enqueue(mRequest, mCallback);
}
}

@Override
public HttpResponse execute(Request request) throws IOException {
if (OK_HTTP_REQUEST) {
mRealHttpClient = new OkHttpClient(this);
} else {
mRealHttpClient = new OriginHttpClient(this);
}
return mRealHttpClient.execute(request);
}

/**
* 异步处理网络请求
*
* @param request  网络请求对象
* @param callback 回调方法
*/
public void enqueue(final Request request, final Callback callback) {
this.mRequest = request;
this.mCallback = callback;
mExecutor.execute(new Runnable() {
@Override
public void run() {
invoke(request, callback.getClass());
}
});
}

/**
* 将服务器数据转化成对应的类型
*
* @param response httpResponse
* @param type     转换成的类型
* @param <T>      返回值类型
* @return 返回对应的值
* @throws IOException
*/
private <T> T convertResponse(HttpResponse response, Type type) throws IOException {
Object result = response;
for (int i = 0; i < mConverts.size(); i++) {
Object data = mConverts.get(i).parse(result, type);
if (data != null) {
result = data;
}
}
return (T) result;
}

private <T> Response parseResponse(T result, HttpResponse httpResponse) {
return new Response(result, httpResponse);
}

public <T> T invoke(Request request, Class responseType) {
Type type = TypeUtils.getType(responseType);
HttpResponse httpResponse;
final T result;
try {
httpResponse = execute(request);
result = convertResponse(httpResponse, type);
} catch (Throwable e) {
e.printStackTrace();
onFailure(e);
if (canRetry()) {
retry();
return null;
}
return null;
}
Response response = parseResponse(result, httpResponse);
onSuccess(response);
return result;

}

private void onSuccess(Response response) {
mCallback.onSuccess(response);
}

private void onFailure(Throwable error) {
mCallback.onFailure(error);
}

public static class Builder {
public static HostnameVerifier DEFAULT_HOST_NAME_VERIFIER = new DefaultHostnameVerifier();
public static SSLSocketFactory DEFAULT_SSL_SOCKET_FACTORY = getDefaultSocketFactory();
private int mWriteTimeOut;
private int mReaderTimeOut;
private int mConnectTimeOut;
public SSLSocketFactory mSSLSocketFactory;
private HostnameVerifier mHostnameVerifier;
private HttpDns mHttpDns;
private ExecutorService mExecutor;
private List<Convert> mConverts;

/**
* 默认的域名校验实现
*/
static class DefaultHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}

/**
* 默认的证书管理
*/
static class DefaultTrustManger implements X509TrustManager {

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}

public static SSLSocketFactory getDefaultSocketFactory() {
SSLContext context = null;
try {
context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{new DefaultTrustManger()}, new SecureRandom());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return context.getSocketFactory();
}

public SSLSocketFactory getSocketFactory(InputStream inputStream) throws Exception {
CertificateFactory factory = CertificateFactory.getInstance("x.509");
X509Certificate certificate = (X509Certificate) factory.generateCertificate(inputStream);

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", certificate);

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
return context.getSocketFactory();
}

/**
* 设置写入时间
*
* @param timeOut 设置的时间值
* @return {@link Builder}
*/
public Builder setWriteTimeOut(int timeOut) {
this.mWriteTimeOut = timeOut;
return this;
}

/**
* 设置读取的时间
*
* @param timeOut 设置的时间值
* @return {@link Builder}
*/
public Builder setReaderTimeOut(int timeOut) {
this.mReaderTimeOut = timeOut;
return this;
}

/**
* 设置网络连接时间
*
* @param timeOut 设置的时间值
* @return {@link Builder}
*/
public Builder setConnectionTimeOut(int timeOut) {
this.mConnectTimeOut = timeOut;
return this;
}

/**
* 设置SSLSocket
*
* @param factory 具体的SSLSocketFactory实现
* @return {@link Builder}
*/
public Builder setSSLSocketFactory(SSLSocketFactory factory) {
this.mSSLSocketFactory = factory;
return this;
}

/**
* 设置域名校验
*
* @param verifier 具体的域名校验实现
* @return {@link Builder}
*/
public Builder setHostnameVerifier(HostnameVerifier verifier) {
this.mHostnameVerifier = verifier;
return this;
}

/**
* 设置HttpDns查询实现
*
* @param dns 具体的HttpDns查询实现
* @return {@link Builder}
*/
public Builder setHttpDns(HttpDns dns) {
this.mHttpDns = dns;
return this;
}

/**
* 设置线程池
*
* @param service 线程池的实现
* @return {@link Builder}
*/
public Builder setExecutors(ExecutorService service) {
this.mExecutor = service;
return this;
}

/**
* 设置转换的类型
*
* @param converts 转换类型的集合
* @return {@link Builder}
*/
public Builder setConverts(List<Convert> converts) {
this.mConverts = converts;
return this;
}

/**
* 判断是否使用的了Http代理
*/
private void proxy() {
String host = System.getProperty("http.proxyHost");
String port = System.getProperty("http.proxyPort");
if (host != null && port != null) {
mHttpDns = null;
}
}

/**
* 构建HttpClient对象
*
* @return {@link HttpClient}
*/
public HttpClient builder() {
proxy();
return new HttpClient(this);
}

}
}


运行后如果出错,会进行重试操作

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐