如何区分http协议的无状态性和长连接?

HttpURLConnection长连接问题 Keep-Alive
[问题点数:28分]
HttpURLConnection长连接问题 Keep-Alive
[问题点数:28分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&随笔 - 70&
评论 - 90&
&&&&&&&&&&&
& & 本文主要从实践角度介绍长、短连接在TCP层面的表现,借助Node.JS搭建后台服务,使用WinHTTP、Ajax做客户端请求测试,最后简单涉及WebSocket。
& & 关键字:长连接、短连接、Node.JS、WebSocket.
& & 一两年前,在理论上对长短连接做了学习,那时的技能以客户端为主,所以也止步于客户端和网络抓包,两年来后台技术渐有把握,打算从前到后的实践一遍。如对理论有不理解的,可以先google/百度 一下,或者看看这篇偏理论的介绍:。
1 短连接的表现
先写个简单的server看看短链接的效果,在8124端口上创建WEB服务,给客户端返回Hello World\n,然后断开连接,代码:
* @file 短连接测试服务
启动: node short.js
* @authoer cswuyg
var os = require('os');
var http = require('http');
var server = http.createServer(function(req, res) {
console.log(req.connection.remoteAddress + ':' + req.connection.remotePort);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
res.destroy();
// destroy immediately
}).listen(8124);
console.log('start ' + os.hostname() + ':8124');
在浏览器访问:http://hostname:8124
使用WireShark抓包:
注意到了吗?上面的FIN 是由8124端口,也就是我们的WEB服务发出来的,及时的销毁了连接。多次刷新浏览器页面,每次都是不同的客户端端口发起请求,不会复用旧连接。
2 长连接的表现
(1)WEB服务代码:
* @file 长连接测试服务器
* 启动: node persistent.js
* ./a.html 为同目录下的ajax请求测试文件
* @authoer cswuyg
var os = require('os');
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(req, res) {
if (/^\/a.html/.test(req.url)) {
fs.createReadStream('a.html').pipe(res);
console.log(req.connection.remoteAddress + ':' + req.connection.remotePort);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8124);
server.setTimeout(0);
//设置不超时,所以服务端不会主动关闭连接
console.log('start ' + os.hostname() + ':8124');
(2)使用WinHTTP测试:
如果我们使用WinHTTP去获取数据,在这份代码上做修改:
代码节选:
const wchar_t* lpszAcceptedType[] = {L"*/*", NULL};
request_handle_ = ::WinHttpOpenRequest(connect_handle, L"GET", url_path_.c_str(), L"HTTP/1.1", WINHTTP_NO_REFERER, lpszAcceptedType, 0);
if (request_handle_ == NULL)
return FALSE;
DWORD time_out = 5000;
::WinHttpSetOption(request_handle_, WINHTTP_OPTION_CONNECT_TIMEOUT, &time_out, sizeof(DWORD));
::WinHttpSendRequest(request_handle_, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
::WinHttpReceiveResponse(request_handle_, NULL);
//测试代码,不惧goto~
代码思路就是connect handle打开之后,后面不同url的请求(当然是同域名下的)可以复用这个connect handle。
使用WireShark抓包,效果:
注:WinHTTP connect handle复用这是浏览器开发者的事情,WEB开发者不会关心到它。
(3)如果我们使用js代码来测试长连接效果呢?
使用ajax,
&script type="text/javascript" src="/jquery/2.1.4/jquery.min.js"&&/script&
function callNode() {
cache : false,
url : 'http://xxxxxyouhost:8124',
data : {},
success : function(response, code, xhr) {
console.log(response);
console.log(code);
callNode();
callNode();
在浏览器访问:http://hostname:8124/a.html
后台上看效果:
刷刷刷的显示出客户端的多次请求都是一样的IP和端口。
3、WebSocket
从WEB开发者最直接的感受来说,终于,可以不用轮询了,只需要使用WebSocket就可以实现全双工通信,要给客户端推送数据更方便了。
从HTTP优化的角度来说:短连接发展到长连接,省略了重复的三次握手,WebSocket的出现,则把HTTP HEADER也省略掉了。而WebSocket,它不是HTTP协议。
WebSocket在底层的表现就是保持连接不断开,客户端既能接收数据也能发送数据,服务端既能接收数据也能发送数据。这在socket层面并没有什么特别,socket的接收缓存区和发送缓存区是分开的,既可以接收也可以发送。对于从socket层面写服务和应用的人来说,WebSocket并不稀奇,譬如,写一个聊天室,连接可以一直不断开的发送和接收数据。对于做WEB开发的朋友,则有很大不同,之前HTTP请求,每一次传输数据,不管是不是用了长连接都是需要有头部信息,而现在有了WebSocket,一个连接可以一直保持着,不发出FIN包,可以收发数据,是长连接,且多次请求不需要有多个头部信息。(一般的http请求,5分钟无响应后,chrome浏览器主动断开连接),
每一次HTTP请求都要走一遍完整的HTTP协议,这让那些需要实时传输数据的朋友很辛苦,虽然HTTP1.1带来了长连接,不用每一次都重新三次握手建立连接,省略了握手的浪费,但是长连接里每一次请求的的HTTP头都是一样的,也还是很浪费,要把长连接里的多次请求的HTTP头也消灭掉,消灭掉之后的协议叫做WebSocket,这个名字也很写实,就像是把Socket层面的东西暴露给上层应用了。
浏览器为了支持WebSocket,可能会做哪些事情呢? 1是去掉超时关闭连接,这种协议就不用主动关闭了;2给后端发数据时,非首次请求不发出HTTP HEADER,后面的多次数据传输都不用再起HTTP连接了;3可以随时接收发送数据,之前都是需要客户端发起请求,然后服务端回应这样的模式来传输数据。 另外,还会做校验、编码之类的工作。
在做实际开发的时候,有浏览器支持还不够,后台也需要支持,Node上有socket.io模块可用。
在使用WebSocket的时候,要注意,后台可能经过一个个的代理,代理可能不认识WebSocket协议,可能会有超时断开连接的逻辑,这会导致长连接无法保持。&
使用WebSocket协议做聊天室,抓包:
说明:1、WebSocket借助了HTTP协议;2、这个tcp stream不会终止,它的传输内容会随着客户端跟服务端的通信而增长。
&WebSocket连接建立时的抓包:
&从HTTP1.0、长连接、WebSocket的发展,是不是可以看出:从无状态发展到有状态?无状态在做分布式/高并发的时候相当重要,但在明明就是有状态的场景下强制使用无状态就坏事了。
文中所涉及Node和html代码见github:.
本文所在:&
如有错误请指正.
学习参考://nodejs-socketio/
阅读(...) 评论()查看: 11586|回复: 24
关于Android上实现HTTP长连接功能
该用户从未签到主题帖子e币
如题,就是实现类似WEB IM即时通讯问题。
现在是通过HTTP,轮询机制,隔一段时间轮询一次服务器的内容并更新。
上面那种机制比较浪费流量,现在想通过HTTP长连接实现。即保持连接,服务器有新数据立即返回客户端。
有木有好一点的例子,或者说说思路。求各位大神指导
服务器收到心跳包之后,就要处理吧,他怎么知道这个是心跳包呢?
然后他一看,我靠,这包里面什么都木有,于是什么裸机操作都不用做了,但是,因为这个过程,你们的这个连接又开始新的超时计算了。当快到断开的时候,你的下一个心跳包又来了,这样又重新开始超时计算,结果就是,你不断的用心跳包维持这个连接,使之不断开。 ...
该用户从未签到主题帖子e币
codeBear 发表于
恩恩,有的不是很清楚。& &服务器收到心跳包后,会不会返回信息?& & 然后连接会不会断? ...
服务器收到心跳包之后,就要处理吧,他怎么知道这个是心跳包呢?
然后他一看,我靠,这包里面什么都木有,于是什么裸机操作都不用做了,但是,因为这个过程,你们的这个连接又开始新的超时计算了。当快到断开的时候,你的下一个心跳包又来了,这样又重新开始超时计算,结果就是,你不断的用心跳包维持这个连接,使之不断开。
哈哈,这个描述一下就懂了。
超时是不是服务器那边设置的?
还有现在是需要:服务器有新数据才响应我,没有新数据保持空闲(就是上面那种长连接)。
我客户端这边要怎样才能知道服务器返回了新数据?
签到天数: 6 天连续签到: 1 天[LV.2]偶尔看看I主题帖子e币
很多是用轮询机制的,保持连接就是这样的,你需要维护心跳消息,不过我感觉这部分教给客户端做比较合适。
另外,可以看下msnp12的协议。其实协议做好了,要重在优化,你优化好了,不会浪费你很多流量的。
嗯,现在就是要求客户端做。服务器已经实现了。其实怎么维持连接哦?
我用HTTP协议,每次请求,他都直接返回。然后关闭了。&
该用户从未签到主题帖子e币
在想服务器请求的时候加入Keep-Alive,并保存保存服务器发过来的Cookie,这样或许可以,比如使用HttpURLConnection进行HTTP请求的时候:
httpURLConnection.setRequestProperty(&Connection&, &Keep-Alive&);
httpURLConnection.connect();
String setCookie = httpURLConnection.getHeaderField(&Set-Cookie&);
cookie = setCookie.substring(0, setCookie.indexOf(&;&));
然后再以后的请求中加入Cookie:httpURLConnection.setRequestProperty(&Cookie&, cookie);
我也不知道这样行不行,LZ可以试试看
鬼谷,这孩子,居然在网上粘贴代码。那个我刚刚看过...
该用户从未签到主题帖子e币
鬼谷子 发表于
在想服务器请求的时候加入Keep-Alive,并保存保存服务器发过来的Cookie,这样或许可以,比如使用HttpURLCon ...
鬼谷,这孩子,居然在网上粘贴代码。那个我刚刚看过...&&不行。。
该用户从未签到主题帖子e币
haoliuyou 发表于
很多是用轮询机制的,保持连接就是这样的,你需要维护心跳消息,不过我感觉这部分教给客户端做比较合适。
嗯,现在就是要求客户端做。服务器已经实现了。其实怎么维持连接哦?&&我用HTTP协议,每次请求,他都直接返回。然后关闭了。
Http1.1的协议在连接后关闭连接的权利在客户端手上&
签到天数: 6 天连续签到: 1 天[LV.2]偶尔看看I主题帖子e币
codeBear 发表于
嗯,现在就是要求客户端做。服务器已经实现了。其实怎么维持连接哦?&&我用HTTP协议,每次请求,他都直接 ...
是这样的 ,这个消息是靠客户端来维护,客户端来发送心跳消息,然后服务器根据这个来记录谁在线,当服务器需要的时候,服务器就去主动请求在线的客户端发送消息。
客户端发送心跳包,是不是正常的请求?那服务器收到心跳包并应答后,连接不是断了吗?&
该用户从未签到主题帖子e币
haoliuyou 发表于
是这样的 ,这个消息是靠客户端来维护,客户端来发送心跳消息,然后服务器根据这个来记录谁在线,当服务 ...
客户端发送心跳包,是不是正常的请求?那服务器收到心跳包并应答后,连接不是断了吗?
签到天数: 6 天连续签到: 1 天[LV.2]偶尔看看I主题帖子e币
codeBear 发表于
客户端发送心跳包,是不是正常的请求?那服务器收到心跳包并应答后,连接不是断了吗? ...
对的,发送心跳宝就是在没有动作的时候维护一个连接。
最后问一下,怎么发送心跳包。java的HttpURLConnection在什么时候关闭的呢?&
该用户从未签到主题帖子e币
最后问一下,怎么发送心跳包。java的HttpURLConnection在什么时候关闭的呢?
该用户从未签到主题帖子e币
Http的协议特定不就是无连接吗 无状态吗,http1.0的协议是请求 服务端返回结果 服务端关闭,http1.1是有长连接的把 貌似要keep-alive 但是也是客户端主动发送请求的吧,关闭的时候是客户端关闭。 长不长链接要看协议用的哪个个版本。
1.1的协议默认是Keep alive。但是请求-应答后,连接就关了。keep alive需要发心跳包维持长连接,这一步不会&
该用户从未签到主题帖子e币
codeBear 发表于
嗯,现在就是要求客户端做。服务器已经实现了。其实怎么维持连接哦?&&我用HTTP协议,每次请求,他都直接 ...
Http1.1的协议在连接后关闭连接的权利在客户端手上
恩恩,明白。现在要解决的问题是怎样通过心跳包维持连接&
该用户从未签到主题帖子e币
启动客户端SocketServer,服务器段作为socket。。。。
公司规定要用HTTP&
该用户从未签到主题帖子e币
haoliuyou 发表于
对的,发送心跳宝就是在没有动作的时候维护一个连接。
最后问一下,怎么发送心跳包。java的HttpURLConnection在什么时候关闭的呢?
该用户从未签到主题帖子e币
zyc1314199 发表于
启动客户端SocketServer,服务器段作为socket。。。。
公司规定要用HTTP
社区贡献者
eoeAndriod社区贡献网友
QQ已认证,此人靠谱
推荐阅读热门话题
619901842415415374321272263257252249234223215715
半小时前1&小时前1&小时前2&小时前2&小时前3&小时前3&小时前3&小时前昨天&23:56昨天&23:35昨天&22:06昨天&20:06昨天&17:26昨天&16:50昨天&16:35昨天&16:33
Powered by如何理解HTTP协议的“无连接,无状态”特点?
是一个属于应用层的面向对象的协议,HTTP 协议一共有五大特点:1、支持客户/服务器模式;2、简单快速;3、灵活;4、无连接;5、无状态。
无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
早期这么做的原因是 HTTP 协议产生于互联网,因此服务器需要处理同时面向全世界数十万、上百万客户端的网页访问,但每个客户端(即)与服务器之间交换数据的间歇性较大(即传输具有突发性、瞬时性),并且网页浏览的联想性、发散性导致两次传送的数据关联性很低,大部分通道实际上会很空闲、无端占用资源。因此 HTTP 的设计者有意利用这种特点将协议设计为请求时建连接、请求完释放连接,以尽快将资源释放出来服务其他客户端。
随着时间的推移,网页变得越来越复杂,里面可能嵌入了很多图片,这时候每次访问图片都需要建立一次 TCP 连接就显得很低效。后来,Keep-Alive 被提出用来解决这效率低的问题。
Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。市场上的大部分 Web 服务器,包括 iPlanet、IIS 和 Apache,都支持 HTTP Keep-Alive。对于提供静态内容的网站来说,这个功能通常很有用。但是,对于负担较重的网站来说,这里存在另外一个问题:虽然为客户保留打开的连接有一定的好处,但它同样影响了性能,因为在处理暂停期间,本来可以释放的资源仍旧被占用。当Web服务器和应用服务器在同一台机器上运行时,Keep-Alive 功能对资源利用的影响尤其突出。
这样一来,客户端和服务器之间的 HTTP 连接就会被保持,不会断开(超过 Keep-Alive 规定的时间,意外断电等情况除外),当客户端发送另外一个请求时,就使用这条已经建立的连接。
无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。即我们给服务器发送 HTTP 请求之后,服务器根据请求,会给我们发送数据过来,但是,发送完,不会记录任何信息。
HTTP 是一个无状态协议,这意味着每个请求都是独立的,Keep-Alive 没能改变这个结果。
缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
HTTP 协议这种特性有优点也有缺点,优点在于解放了服务器,每一次请求&点到为止&不会造成不必要连接占用,缺点在于每次请求会传输大量重复的内容信息。
客户端与服务器进行动态交互的 Web 应用程序出现之后,HTTP 无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品。于是,两种用于保持 HTTP 连接状态的技术就应运而生了,一个是 Cookie,而另一个则是 Session。
Cookie可以保持登录信息到用户下次与服务器的会话,换句话说,下次访问同一网站时,用户会发现不必输入用户名和密码就已经登录了(当然,不排除用户手工删除Cookie)。而还有一些Cookie在用户退出会话的时候就被删除了,这样可以有效保护个人隐私。
Cookies 最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续,这些都是 Cookies 的功用。另一个重要应用场合是&购物车&之类处理。用户可能会在一段时间内在同一家网站的不同页面中选择不同的商品,这些信息都会写入 Cookies,以便在最后付款时提取信息。
与 Cookie 相对的一个解决方案是 Session,它是通过服务器来保持状态的。
当客户端访问服务器时,服务器根据需求设置 Session,将会话信息保存在服务器上,同时将标示 Session 的 SessionId 传递给客户端浏览器,浏览器将这个 SessionId 保存在内存中,我们称之为无过期时间的 Cookie。浏览器关闭后,这个 Cookie 就会被清掉,它不会存在于用户的 Cookie 临时文件。
以后浏览器每次请求都会额外加上这个参数值,服务器会根据这个 SessionId,就能取得客户端的数据信息。
如果客户端浏览器意外关闭,服务器保存的 Session 数据不是立即释放,此时数据还会存在,只要我们知道那个 SessionId,就可以继续通过请求获得此 Session 的信息,因为此时后台的 Session 还存在,当然我们可以设置一个 Session 超时时间,一旦超过规定时间没有客户端请求时,服务器就会清除对应 SessionId 的 Session 信息。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'}

我要回帖

更多关于 无状态协议 的文章

更多推荐

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

点击添加站长微信