谁帮我申请一个QQ 我小米手机申请解锁不了了 用来打游戏

> 博客详情
摘要: 在进行Android应用开发时,网络通信功能是不可或缺的模块之一。为了能让应用保持好的用户交互体验和高效的网络通信性能,程序员GG要进行大量的多线程开发以及线程之间的并发同步处理,稍有不慎,伤得可就不仅仅是测试软妹子的心,还有可能是自己的饭碗。async-http-client开源库为程序员GG封装了http数据通信的各种底层处理,包括异步、数据转换、文件分段下载等等,我们只需要关注功能的本身所需要的数据处理部分就可以安心泡妹子了。
0. 文前闲话
&&&&作为一个Android开发的大龄初学者,面对扑面而来的各种姿势的Android的开源组件,让人倍感窒息,难以应对。无奈为了养家糊口,虽然已近不惑,人老珠黄,也只能废寝忘食,逐个体位细细揣摩研究,不断以身实践,争取早日小成。
&&&&话说那是一个阳光明媚的下午,我坐在街口转角处优雅的网络会所里,品着一杯上好的Coca-Cola,研读着oschina客户端源码,身旁不时传来:“一起上搞死他,他没蓝了...!”。
&&&&从火蚁(oschina客户端的开发者之一,向他们致敬)那里知道了async-http-client开源库,为了千千万万个没过英语四级的程序猿GG,就在这里翻译个作者写的"用户说明书"先...
1. async-http-client开源库简介
&&&&async-http-client库是一个基于回调函数的Http异步通信客户端Android组件,是在Apache的HttpClient库的基础上开发构建而成的。这里的异步,是指它所有的网络请求都是在app的UI线程之外的独立工作线程中执行。而开发者通过利用Android的消息处理机制,把我们所需要编写的回调函数放在这个回调函数的创建线程中执行(一般就是UI线程),所以使用起来非常方便,有了它,妈妈再也不用担心我被多线程同步搞死了。除了能应用在开发普通App上,还可以用来开发Service或后台线程,async-http-client库可以自已分辨是被用在哪一种应用下,不需要额外的设置。
异步方式发起Http请求,可以使用匿名回调函数处理网络应答;
在UI主线程之外的工作线程发起Http请求;
通过使用线程池解决了资源并发的效率问题;
通过使用RequestParams类,可完成GET/POST的参数构建;
支持文件的分段下载功能;
支持上传JSON数据流;
对重定向循环、重定向相对路径异常进行了处理
代码体积小,全部功能只占90kb;
专门针对移动网络的不稳定性,对请求重发进行了优化,实现了自动智能处理;
传输时支持数据压缩,可自动对应答进行gzip解压处理;
使用BinaryHttpResponseHandler,可进行较底层的tcp/ip协议数据通信;
JsonHttpResponseHandler内嵌JSON语法分析功能,可完成JSON数据解析;
FileAsyncHttpResponseHandler可直接将应答保存到本地文件中;
支持cookie的持久化,可使用App的SharedPreferences保存cookie信息;
通过BaseJsonHttpResponseHandler可与Jackson JSON, Gson等第三方JSON框架库集成;
SaxAsyncHttpResponseHandler支持SAX语法分析
除了UTF-8,还支持其它语言编码。
1.2 使用async-http-client的大型应用
Frontline Commando (Glu Games)
(以上应用我一个都没用过,反正说明async-http-client很diao就对了)
2. async-http-client库的安装和基本应用
2.1 基本应用方法
&&&&1.&在Gradle build脚本中增加
dependencies&{
&&&&compile&'com.loopj.android:android-async-http:1.4.8'
& & 2. 引入http包
import&com.loopj.android.http.*;
& & 3. 创建AsyncHttpClient 实例,并发出请求
AsyncHttpClientclient&=&new&AsyncHttpClient();
client.get("",&new&AsyncHttpResponseHandler(){
&&&&@Override
&&&&public&void&onStart(){
&&&&&&&&//&called&before&request&is&started
&&&&@Override
&&&&public&void&onSuccess(int&statusCode,&Header[]&headers,&byte[]&response){
&&&&&&&&//&called&when&response&HTTP&status&is&"200&OK"
&&&&@Override
&&&&public&void&onFailure(int&statusCode,&Header[]&headers,
&&&&&&&&&&&&&&&&&&&&&&&&&&byte[]&errorResponse,&Throwablee){
&&&&&&&&//&called&when&response&HTTP&status&is&"4XX"&(eg.&401,&403,&404)
&&&&@Override
&&&&public&void&onRetry(int&retryNo){
&&&&&&&&//&called&when&request&is&retried
2.2 推荐使用方法:创建静态Http客户端
&&&&创建AsyncHttpClient的静态实例进行通信更加方便,以使用Twitter提供的Api为例(此处使用Twitter作例子,站在大墙里面的我们看看就行了):
import&com.loopj.android.http.*;
public&class&TwitterRestClient&{
&&&&private&static&final&String&BASE_URL&=&"/1/";
&&&&private&static&AsyncHttpClient&client&=&new&AsyncHttpClient();
&&&&public&static&void&get(String&url,&RequestParams&params,&AsyncHttpResponseHandler&responseHandler)&{
&&&&&&&&client.get(getAbsoluteUrl(url),&params,&responseHandler);
&&&&public&static&void&post(String&url,&RequestParams&params,&AsyncHttpResponseHandler&responseHandler)&{
&&&&&&&&client.post(getAbsoluteUrl(url),&params,&responseHandler);
&&&&private&static&String&getAbsoluteUrl(String&relativeUrl)&{
&&&&&&&&return&BASE_URL&+&relativeU
& & TwitterRestClient 类中创建了一个AsyncHttpClient的静态实例,通过静态实例与Twitter进行数据通信,共有两个对外的接口函数get,set,也都是静态的。下面是如何在代码中使用这个类:
import&org.json.*;
import&com.loopj.android.http.*;
class&TwitterRestClientUsage&{
&&&&public&void&getPublicTimeline()&throws&JSONException&{
&&&&&&&&TwitterRestClient.get("statuses/public_timeline.json",&null,&
&&&&&&&&&&&&&&&&new&JsonHttpResponseHandler()&{
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onSuccess(int&statusCode,&Header[]&headers,&
&&&&&&&&&&&&&&&&&&&&JSONObject&response)&{
&&&&&&&&&&&&&&&&//&If&the&response&is&JSONObject&instead&of&expected&JSONArray
&&&&&&&&&&&&}
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onSuccess(int&statusCode,&Header[]&headers,&
&&&&&&&&&&&&&&&&&&&&JSONArray&timeline)&{
&&&&&&&&&&&&&&&&//&Pull&out&the&first&event&on&the&public&timeline
&&&&&&&&&&&&&&&&JSONObject&firstEvent&=&timeline.get(0);
&&&&&&&&&&&&&&&&String&tweetText&=&firstEvent.getString("text");
&&&&&&&&&&&&&&&&//&Do&something&with&the&response
&&&&&&&&&&&&&&&&System.out.println(tweetText);
&&&&&&&&&&&&}
&&&&&&&&});
&&&&这里使用了匿名回调函数,并且是JsonHttpResponseHandler类型,它内嵌了Json语言解析器,可直接在处理函数中使用对应答数据解析后的Json数据,真是即方便又快捷。
3. 使用PersistentCookieStore进行Cookie的持久化存储
&&&&async-http-client库包含一个PersistentCookieStore类,这个类实现了CookieStore接口(源自Apache HttpClient包),可自动将cookie信息保存到应用的SharedPreferences储存中。
&&&&如果你的应用需要使用cookie维护用户授权session,这是非常有用,方便的。即使关闭了app或重新启动app,应用也可以保持用户已登录的状态。
&&&&首先创建一个AsyncHttpClient实例:
AsyncHttpClient&myClient&=&new&AsyncHttpClient();
&&&&为这个实例设置一个新建的PersistentCookieStore的实例以进行cookie存储,调用这个PersistentCookieStore实例的构造函数时,使用一个activity或application context作参数(一般用this就可以了):
PersistentCookieStore&myCookieStore&=&new&PersistentCookieStore(this);
myClient.setCookieStore(myCookieStore);
&&&&这样由服务端接收到的cookie将会自动存储在你的android设备上。如果要添加自己的cookie,只需要构建一个新的cookie并调用addCookie函数:
BasicClientCookie&newCookie&=&new&BasicClientCookie("cookiesare",&"awesome");
newCookie.setVersion(1);
newCookie.setDomain("");
newCookie.setPath("/");
myCookieStore.addCookie(newCookie);
4. 使用RequestParams增加GET/POST参数
4.1 为请求增加参数
& & 大部分应用的url请求都需要带各种参数,在Get/Post请求时增加参数,可使用RequestParams类。
& & 可以使用以下三种方法构建RequestParams实例:
& & 1. 创建一个空的RequestParams实例,并增加参数:
RequestParams&params&=&new&RequestParams();
params.put("key",&"value");
params.put("more",&"data");
& & 2. 只有一个参数,创建RequestParams实例:
RequestParams&params&=&new&RequestParams("single",&"value");
& & 3. 利用已存在的Map键值对创建RequestParams实例:
HashMap&String,&String&&paramMap&=&new&HashMap&String,&String&();
paramMap.put("key",&"value");
RequestParams&params&=&new&RequestParams(paramMap);
4.2 利用RequestParams上传文件
& & RequestParams类还可以用来实现文件分段上传,有以下三种实现方式:
& & 1. 将InputStream作为参数加入RequestParams:
InputStream&myInputStream&=&
RequestParams&params&=&new&RequestParams();
params.put("secret_passwords",&myInputStream,&"passwords.txt");
& & 2. 直接将File对象增加到RequestParams中:
File&myFile&=&new&File("/path/to/file.png");
RequestParams&params&=&new&RequestParams();
&&&&params.put("profile_picture",&myFile);
}&catch(FileNotFoundException&e)&{}
& & 3. 使用二进制字节数组:
byte[]&myByteArray&=&
RequestParams&params&=&new&RequestParams();
params.put("soundtrack",&new&ByteArrayInputStream(myByteArray),&"she-wolf.mp3");
5. 使用FileAsyncHttpResponseHandler下载二进制数据
& & FileAsyncHttpResponseHandler用来获取二进制数据,比如图像、声音等文件。
AsyncHttpClient&client&=&new&AsyncHttpClient();
client.get("/file.png",&
&&&&&&&&new&FileAsyncHttpResponseHandler(/*&Context&*/&this)&{
&&&&@Override
&&&&public&void&onSuccess(int&statusCode,&Header[]&headers,&File&response)&{
&&&&&&&&//&Do&something&with&the&file&`response`
6. 为HTTP通信增加授权认证
& & 在实际应用环境中,某些服务器资源需要用户名/密码授权认证才能访问,这类资源访问需要使用HTTP Basic Access Authentication协议,请求才能被处理。可以使用setBasicAuth函数提供认证信息。
& & 为主机或域名访问设置用户名/密码,默认状态认证信息对所有主机、端口或域名有效。
AsyncHttpClient&client&=&new&AsyncHttpClient();
client.setBasicAuth("username","password/token");
client.get("");
& & 更为推荐的方式是对特定的主机或端口提供授权认证信息:
AsyncHttpClient&client&=&new&AsyncHttpClient();
client.setBasicAuth("username","password",&
&&&&&&&&new&AuthScope("",&80,&AuthScope.ANY_REALM));
client.get("");
人打赏支持
码字总数 4396
平时只喜欢看,现在慢慢练着整理出来
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥
& 开源中国(OSChina.NET) |
开源中国社区(OSChina.net)是工信部
指定的官方社区Tornado 4.3 文档翻译: 用户指南-介绍 - 简书
Tornado 4.3 文档翻译: 用户指南-介绍
Tornado 4.3于日发布,该版本正式支持Python3.5的async/await关键字,并且用旧版本CPython编译Tornado同样可以使用这两个关键字,这无疑是一种进步。其次,这是最后一个支持Python2.6和Python3.2的版本了,在后续的版本了会移除对它们的兼容。现在网络上还没有Tornado4.3的中文文档,所以为了让更多的朋友能接触并学习到它,我开始了这个翻译项目,希望感兴趣的小伙伴可以一起参与翻译,项目地址是,翻译好的文档在直接可以看到。欢迎Issues or PR。
是一个Python web框架和异步网络库起初由 开发. 通过使用非阻塞网络I/O, Tornado 可以支持上万级的连接,处理,, 和其他需要与每个用户保持长久连接的应用.
Tornado 大体上可以被分为4个主要的部分:
web框架 (包括创建web应用的 RequestHandler 类,还有很多其他支持的类).
HTTP的客户端和服务端实现 (HTTPServer and AsyncHTTPClient).
异步网络库 (IOLoop and IOStream),为HTTP组件提供构建模块,也可以用来实现其他协议.
协程库 (tornado.gen) 允许异步代码写的更直接而不用链式回调的方式.
Tornado web 框架和HTTP server 一起为提供了一个全栈式的选择.在WSGI容器 (.WSGIAdapter) 中使用Tornado web框架或者使用Tornado HTTP server作为一个其他WSGI框架(.WSGIContainer)的容器,这样的组合方式都是有局限性的.为了充分利用Tornado的特性,你需要一起使用Tornado的web框架和HTTP server.
Programmer? Linuxer?Vim党?Python?ACG?
...HttpClient容易忽视的细节——连接关闭 - 修炼中。。。 - ITeye技术网站
博客分类:
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod("http://www.apache.org");
client.executeMethod(method);
byte[] responseBody =
responseBody = method.getResponseBody();
} catch (HttpException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
method.releaseConnection();
大部分人使用HttpClient都是使用类似上面的事例代码,包括Apache官方的例子也是如此。最近我在使用HttpClient是发现一次循环发送大量请求到服务器会导致APACHE服务器的链接被占满,后续的请求便排队等待。
我服务器端APACHE的配置
Timeout 30
KeepAlive On
#表示服务器端不会主动关闭链接
MaxKeepAliveRequests 100
KeepAliveTimeout 180
因此这样的配置就会导致每个链接至少要过180S才会被释放,这样在大量请求访问时就必然会造成链接被占满,请求等待的情况。
在通过DEBUH后发现HttpClient在method.releaseConnection()后并没有把链接关闭,这个方法只是将链接返回给connection manager。如果使用HttpClient client = new HttpClient()实例化一个HttpClient connection manager默认实现是使用SimpleHttpConnectionManager。SimpleHttpConnectionManager有个构造函数如下
* The connection manager created with this constructor will try to keep the
* connection open (alive) between consecutive requests if the alwaysClose
* parameter is set to &tt&false&/tt&. Otherwise the connection manager will
* always close connections upon release.
* @param alwaysClose if set &tt&true&/tt&, the connection manager will always
close connections upon release.
public SimpleHttpConnectionManager(boolean alwaysClose) {
this.alwaysClose = alwaysC
看方法注释我们就可以看到如果alwaysClose设为true在链接释放之后connection manager 就会关闭链。在我们HttpClient client = new HttpClient()这样实例化一个client时connection manager是这样被实例化的
this.httpConnectionManager = new SimpleHttpConnectionManager();
因此alwaysClose默认是false,connection是不会被主动关闭的,因此我们就有了一个客户端关闭链接的方法。
方法一:
把事例代码中的第一行实例化代码改为如下即可,在method.releaseConnection();之后connection manager会关闭connection 。
HttpClient client = new HttpClient(new HttpClientParams(),new SimpleHttpConnectionManager(true) );
方法二:
实例化代码使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上
((SimpleHttpConnectionManager)client.getHttpConnectionManager()).shutdown();
shutdown源代码很简单,看了一目了然
public void shutdown() {
httpConnection.close();
方法三:
实例化代码使用:HttpClient client = new HttpClient();
在method.releaseConnection();之后加上
client.getHttpConnectionManager().closeIdleConnections(0);此方法源码代码如下:
public void closeIdleConnections(long idleTimeout) {
long maxIdleTime = System.currentTimeMillis() - idleT
if (idleStartTime &= maxIdleTime) {
httpConnection.close();
将idleTimeout设为0可以确保链接被关闭。
以上这三种方法都是有客户端主动关闭TCP链接的方法。下面再介绍由服务器端自动关闭链接的方法。
方法四:
代码实现很简单,所有代码就和最上面的事例代码一样。只需要在HttpMethod method = new GetMethod("http://www.apache.org");加上一行HTTP头的设置即可
method.setRequestHeader("Connection", "close");
看一下HTTP协议中关于这个属性的定义:
HTTP/1.1 defines the "close" connection option for the sender to signal that the connection will be closed after completion of the response. For example,
&&&&&& Connection: close
现在再说一下客户端关闭链接和服务器端关闭链接的区别。如果采用客户端关闭链接的方法,在客户端的机器上使用netstat –an命令会看到很多TIME_WAIT的TCP链接。如果服务器端主动关闭链接这中情况就出现在服务器端。
参考WIKI上的说明http://wiki.apache.org/HttpComponents/FrequentlyAskedConnectionManagementQuestions
The TIME_WAIT state is a protection mechanism in TCP. The side that closes a socket connection orderly will keep the connection in state TIME_WAIT for some time, typically between 1 and 4 minutes.
TIME_WAIT的状态会出现在主动关闭链接的这一端。TCP协议中TIME_WAIT状态主要是为了保证数据的完整传输。具体可以参考此文档:
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html#ss2.7
另外强调一下使用上面这些方法关闭链接是在我们的应用中明确知道不需要重用链接时可以主动关闭链接来释放资源。如果你的应用是需要重用链接的话就没必要这么做,使用原有的链接还可以提供性能。
浏览 56214
论坛回复 /
(8 / 29894)
但使用netstat发现很多TIME_WAIT,时间长点后会出现端口都被占用的状况 address already in use :connect,使用HttpURLConnection.disconnect()也没有效果。
如果你是应为客户端出现很多的TIME_WAIT造成端口占用,你不妨试一下“方法四”在HTTP请求头上设置"Connection", "close"这样服务器会来主动关闭链接,这样就不会在客户端产生很多的TIME_WAIT
另外强调一下使用上面这些方法关闭链接是在我们的应用中明确知道不需要重用链接时可以主动关闭链接来释放资源。如果你的应用是需要重用链接的话就没必要这么做,使用原有的链接还可以提供性能。
正如你所说,实际上是只有并发量很高的时候才会发生链接占满的情况。
而如果没有这么高的并发量,我们没必要去实现代码来关闭连接。
因为我们在代码中实现主动关闭的功能的同时,也丧失了性能上的优势。
因此,我觉得遇到这种情况,应该把设置中的keepAliveTimeout调低,显得更好一些。
1. Timeout 30
2. KeepAlive On
#表示服务器端不会主动关闭链接
3. MaxKeepAliveRequests 100
4. KeepAliveTimeout 180
不过,这里提供的HttpClient关闭的详细信息,还是很有价值的。
浏览: 176438 次
来自: 杭州
[i]引用[img][url][flash=200,200][ ...
sqtds 写道文章写的很好,浅显易懂!!!com.taoba ...
悲剧啊,google code 被墙了最近在测试一个第三方API,准备集成在我们的网站应用中。API的调用使用的是.NET中的HttpClient,由于这个API会在关键业务中用到,对调用API的整体响应速度有严格要求,所以对HttpClient有了格外的关注。
开始测试的时候,只在客户端通过HttpClient用PostAsync发了一个http post请求。测试时发现,从创建HttpClient实例,到发出请求,到读取到服务器的响应数据总耗时在2s左右,而且多次测试都是这样。2s的响应速度当然是无法让人接受的,我们希望至少控制在100ms以内。于是开始追查这个问题的原因。
在API的返回数据中包含了该请求在服务端执行的耗时,这个耗时都在20ms以内,问题与服务端API无关。于是把怀疑点放到了网络延迟上,但ping服务器的响应时间都在10ms左右,网络延迟的可能性也不大。
当我们正准备换一个网络环境进行测试时,突然想到,我们的测试方式有些问题。我们只通过HttpClient发了一个PostAsync请求,假如HttpClient在第一次调用时存在某种预热机制(比如在EF中就有这样的),现在2s的总耗时可能大多消耗在HttpClient的预热上。
于是修改测试代码,将调用由1次改为100次,然后恍然大悟地发现&&只有第1次是2s,接下来的99次都在100ms以内。果然是HttpClient的某种预热机制在搞鬼!
既然知道了是HttpClient预热机制的原因,那我们可以帮HttpClient进行热身,减少第一次请求的耗时。我们尝试了一种预热方式,在正式发http post请求之前,先发一个http head请求,代码如下:
_httpClient.SendAsync(new HttpRequestMessage {
Method = new HttpMethod("HEAD"),
RequestUri = new Uri(BASE_ADDRESS + "/") })
.Result.EnsureSuccessStatusCode();
经测试,通过这种热身方法,可以将第一次请求的耗时由2s左右降到1s以内(测试结果是700多ms)。
在知道第1次HttpClient请求耗时2s的真相之后,我们将目光转向了剩下的99次耗时100ms以内的请求,发现绝大部分请求都在50ms以上。有没有可能将之降至50ms以下?而且,之前一直有这样的纠结:每次调用是不是一定要对HttpClient进行Dispose()?是不是要将HttpClient单例或者静态化(声明为静态变量)?借此机会一起研究一下。
在HttpClient的背后,有一个对请求响应速度有着不容忽视影响的东东&&TCP连接。一个HttpClient实例会关联一个TCP连接,在对HttpClient进行Dispose时,会关闭TCP连接(我们用Wireshark进行网络抓包也验证了这一点)。
在之前的测试中,我们每次用HttpClient发请求时,都是新建一个HttpClient实例,用完就对它进行Dispose,代码如下:
using (var httpClient = new HttpClient() { BaseAddress = new Uri(BASE_ADDRESS) })
httpClient.PostAsync("/", new FormUrlEncodedContent(parameters));
所以每次请求时都要经历新建TCP连接-&传数据-&关闭连接(也就是通常所说的短连接),而且雪上加霜的是请求用的是https,建立TCP连接时还需要一个基于公私钥加解密的key exchange过程:Client Hello -& Server Hello -& Certificate -& Client Key Exchange -& New Session Ticket。
如果我们想将请求响应时间降至50ms以下,就必须从这个地方下手&&重用TCP连接(也就是通常所说的长连接)。要实现长连接,首先需要的就是在HttpClient第1次请求后不关闭TCP连接(不调用Dispose方法);而要让后续的请求继续使用这个未关闭的TCP连接,我们必须要使用同一个HttpClient实例;而要使用同一个HttpClient实例,就得实现HttpClient的单例或者静态化。之前的3 个问题,由于要解决第1个问题,后2个问题变成了别无选择。
为了实现长连接,我们将HttpClient的调用代码改为如下的样子:
public class HttpClientTest
private static readonly HttpClient _httpC
static HttpClientTest()
_httpClient = new HttpClient() { BaseAddress = new Uri(BASE_ADDRESS) };
//帮HttpClient热身
_httpClient.SendAsync(new HttpRequestMessage {
Method = new HttpMethod("HEAD"),
RequestUri = new Uri(BASE_ADDRESS + "/") })
.Result.EnsureSuccessStatusCode();
public async Task&string& PostAsync()
var response = await _httpClient.PostAsync("/", new FormUrlEncodedContent(parameters));
return await response.Content.ReadAsStringAsync();
然后测试一下请求响应时间:
Elapsed:750ms
Elapsed:31ms
Elapsed:30ms
Elapsed:43ms
Elapsed:27ms
Elapsed:29ms
Elapsed:28ms
Elapsed:35ms
Elapsed:36ms
Elapsed:31ms
除了第1次请求,接下来的99次请求绝大多数都在50ms以内。TCP长连接的效果必须的!
通过Wireshak抓包也验证了长连接的效果:
这时,你也许会产生这样的疑问:将HttpClient声明为静态变量,会不会存在线程安全问题?我们当时也有这样的疑问,后来在stackoverflow上找到了:
As per the comments below (thanks @ischell), the following instance methods are thread safe (all async):
CancelPendingRequests
DeleteAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
HttpClient的所有异步方法都是线程安全的,放心使用。
到这里,HttpClient的问题是不是可以完美收官了?。。。稍等,还有一个问题。
客户端虽然保持着TCP连接,但TCP连接是两口子的事,服务器端呢?你不告诉服务器,服务器怎么知道你要一直保持TCP连接呢?对于客户端,保持TCP连接的开销不大;但是对于服务器,则完全不一样的,如果默认都保持TCP连接,那可是要保持成千上万客户端的连接啊。所以,一般的Web服务器都会根据客户端的诉求来决定是否保持TCP连接,这就是keep-alive存在的理由。
所以,我们还要给HttpClient增加一个Connection:keep-alive的请求头,代码如下:
_httpClient.DefaultRequestHeaders.Connection.Add("keep-alive");
现在终于可以收官了。但是肯定不完美,分享的只是解决问题的过程。
阅读(...) 评论()}

我要回帖

更多关于 申请qq号不用手机号码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信