WebSocket是什么原理?为什么可以实现持久连接?
首发

WebSocket是什么原理?为什么可以实现持久连接?

优质
请用语音读文章

热门回答:

首先需要明白:基于TCP的应用层协议。只要设计者愿意。都是可以实现持久连接的。

你问的方式。大概是在和HTTP做比较。

HTTP

http协议是请求应答式的文本协议。协议设计就是Client-Server模式。出发点是服务端为客户端提供资源。http服务端只能监听和响应来自客户端的请求。http客户端只能发起请求接受响应。这个是HTTP协议本身的设计。双向通信不在设计的考虑之内。

关于Http协议。额外说点:

HTTP1.0/0.9

不支持keep-alive。要完成一次HTTP请求。需要建立一个新的TCP连接。然后发送http请求。待接收响应后关闭连接。

HTTP1.1

默认使用keep-alive。一次HTTP请求完成后不会关闭TCP连接。会继续为下一个HTTP请求服务(可以类比数据库连接池和线程池的设计)。减小建立和关闭TCP连接的开销(三次握手四次挥手)。当然闲置超时后也会关闭。并非楼下所说的“把多个HTTP请求合并为一个”。

HTTP协议的设计无法实现对TCP通道的分用和复用。因为HTTP协议没有请求的唯一标记(仅仅是URL是不行的。原因大家想)用来从同一TCP通道分离不同的HTTP消息。所以一个完整的HTTP请求在发送请求到响应回来之间是独占一个TCP通道的!是不是觉得HTTP对TCP的利用率太低了?而关于pipeline模式。不管在服务端还是客户端排队。HTTP响应依然要通过进入服务端队列的顺序返回。这样才能和客户端HTTP请求队列用顺序做对应!所以pipeline模式某个请求被服务端因为某些原因阻塞了的情况下。后续请求都会阻塞。会引起很大的问题。实际上很少用。

浏览器或者一般HTTP客户端组件为某一个服务器端点(域名+端口)保留4-6条活跃TCP连接。你可以F12观察浏览器。看看同时是几个请求阻塞了就知道你的浏览器设置的多少。比较大的门户网站。比如京东。首页请求非常多。但是大量都需要排队等TCP空闲。限制客户端的连接数量的出发点主要是性能。否则会占用服务器太多Socket资源(考虑socket预留的读写缓冲区。windows的内核对象或者linux的文件句柄)或者变相地造成DoS攻击。

Tips:HTTP客户端组件一般会提供诸如ConnectionLimit的选项让你控制最大TCP连接数。如果你是桌面客户端。或者请求远程服务。不宜设置过大。如果你是内部服务之间调用。可以根据需求合理设置以增加并发性能。

HTTP2.0

针对以上的问题(主要是性能)做了很多改进。这个也会提高很多人在后端不同服务器之间做通信时选择HTTP(我在HTTP2.0出来之前就是自己设计RPC方案)。详细的HTTP2.0的东西。这里不展开了。详细参考官方文档。

HTTP相关知识推荐《HTTP权威指南》以及相关的RFC文档。尽量少去看博客上面支离破碎的小知识。体系化的认知结构对你帮助更大。

WebSocket

WebSocket的出现。就是为了解决http协议不支持双向通信的缺口。所以WebSocket的握手协议就是使用的HTTP消息来Upgrade。

现代的Web场景。服务端推送的需求非常大。这个发展过程中使用的Ajax轮询。Comet等都只是临时解决方案。从设计上看。只为满足需求。一点都不优雅。

Html5规范将WebSocket纳入后。得到了现代几乎所有浏览器的支持。当然IE(10+才支持)仍然是一个巨坑。在乎用户覆盖面的产品依然要通过浏览器是否支持ws来做出降级处理(轮询、长连接)。

websocket协议实现独占一条tcp通道。它负责从tcp流确定消息边界。解析出每个独立的消息包。可进行全双工的双向通信。题主所谓的WebSocket可以实现持久连接。只是的一个服务端WebSocket会话和对应的客户端WebSocket会话在使用一个固定的保持连接的TCP通信而已。一般需要将服务端WebSocket会话和某位用户关联起来(客户单连接后。可以再单独发送凭证验证)。实现给某个用户推送消息。只需根据关联找到对应的WebSocket会话调用发送API即可。

应用

使用单独实现websocket协议的服务\客户端组件。可以更加轻松地实现自定义协议:在websocket的二进制或者文本消息体内或者直接使用websocket的自协议定义机制封装自己定义的协议。

推荐大家如果有些需要自建IM服务器。推送服务器的场合尝试先用WebSocket来实现。负载高(协议头消耗小)。协议简洁。几乎所有客户端(减少了大量的工作)都有对应的开源项目可用。同时还是唯一可以在浏览器上用的双向通信协议(flash和silverlight等插件方式除外)。

如果你要用websocket实现请求应答式的子协议。要点是你要设计唯一的请求标志。响应也将请求标志带回来。然后你就可以从客户端的请求队列中查找响应对应的请求将响应交给上层处理!

特别注意:

关于webcket持久连接。本质上是下层tcp连接的保持。核心问题同样是如何保活。需要考虑Nat失效(基站最突出。一般有效期只有3分钟)或者其它网络原因导致大量半连接存在。解决方案就是合理的心跳时间。一般我设置为2分50秒的样子。

其它

不论是否从事网络编程。都应该花时间学习下TCP/IP协议簇方面的知识。着重理解分层原理。各层的功能和为上层提供了哪些功能。就像这个问题。如果不对TCP有所了解。回答的内容就没多大意义了。阅读一个你比较熟悉的语言的的一种协议(比如http)实现项目的源码。帮助应该很大。

和网络IO密切相关的就是线程。要设计高可用的TCP服务器。必须要熟悉多线程。网络IO和多线程是我认为最重要的两个核心知识点。

关于协议的设计。你可以多学习其他优秀的基于TCP实现的应用层协议。简单的就有Redis的通信协议。里面有阻塞式的消费者队列。那个就需要一条单独的tcp通道。协议设计是很有意思的一件事情。就是mysql和mongodb的通信协议我也不会放过。去看看。会给自己设计协议带来不少的参考价值。

如果时间允许。有标准的协议最好看看RFC文档。现在Chrome的翻译已经很好了。如果英文不太好。问题也不大。

关于TCP/IP相关的书籍

《计算机网络:自顶向下方法》和谢希仁的《计算机网络》都是不错的入门书籍。

《TCP/IP详解》是经典。虽然出版已久。内容是没过时的。

网络应用脱离不了操作系统。所以可以再看看操作系统关于网络IO这一块的设计。

实际开发更多和Socket以及多线程打交道。Windows下面可以看看《Windows核心编程》。

其它的就是开源项目:Nginx。netty等大量优秀的项目都在等你。

还是要感谢大家对我写的东西有那么一点感兴趣。能对大家有所帮助就更好了。

其他观点:

解释WebSocket为什么可以实现持久连接。还是先介绍一些什么是WebSocket。以及它产生的原因是什么。

是什么WebSocket?

WebSocket是一个协议。

协议就是王八的屁股——规定。你可以不遵守。但是别人都遵守你不遵守。你就跟别人玩不到一块去。

WebSocket协议在2008年诞生。2011年成为了国际标准。现在绝大部分浏览器都已经支持了。

产生的原因

其实原因是为了弥补HTTP协议的不足。因为HTTP协议只能由客户端发起请求。并且一个Request要对应一个Response(长链接也是如此)。

举个例子:

我之前做过一个小项目。只有一个页面。展示的是各个分公司当天的业绩。就是挣了多少钱。后台服务是Java。数据库是Mysql。有一张汇总表。内容大概是北京-100万。上海-80万这样的。

流程很简单。HTML页面发起请求到Java。Java访问数据库查询数据。再返回给HTML展示。但是Mysql中的汇总表的数据。是不定期更新的。可能10分钟。可能20分钟。

最简单的做法:HTML中用JS设置一个定时轮询(Polling)。每隔几秒去发起一次请求。获取最新的数据。如果数据没有变化。页面也保持变化;缺点很明显。前端发起的很多请求都是无效的(因为数据没有变化)。

WebSocket的通信原理

而WebSocket。是要在客户端和服务器之间。建立一个通道。建立一个【真的长链接】。

WebSocket是要借助于HTTP。完成一部分工作。我在找到一个WebSocket在线测试的网站。打开之后查看请求和响应(具体网站连接也看下面图片中的信息)。

可以看出来协议里面多了两行:

Upgrade: websocket

Connection: Upgrade

这个就是关键内容了。通过请求告诉服务器:看清楚咯。请求要用WebSocket协议。

服务器会回答:好的。那我就切换到WebSocket协议啦。

到了这时候。HTTP完成它所有工作。客户端和服务器已经建立好了一个通道。下面就按照WebSocket协议进行了。服务端也就可以主动推送信息给客户端(双向)。并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。故此WebSocket也就实现了持久连接。

希望我的回答。能够帮助到你!我将持续分享Java开发、架构设计、程序员职业发展等方面的见解。希望能得到你的关注。

其他观点:

很高兴能够看到和回答这个问题!

WebSocket是什么原理?

WebSocket通过常见的HTTP协议进行数据连接。一般走的是TCP通道。WebSocket是一个允许单TCP连接之间全双工通信的协议。在WebSocket API中。浏览器和服务器只需要一次远程连接。而不是三次远程连接连接到TCP服务器。这样就可以直接持久连接和双向数据传输。

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

缺陷:HTTP的通信只能由客户端发起建立在TCP协议之上WebSocket特点性能开销小通信高效

客户端可以与任意服务器通信

协议标识符ws wss持久化网络通信协议

通常情况下。浏览器向服务器发送一个请求。工作完成后再向客户端返回一个消息。如果需要主动向浏览器提供数据。可以使用Web套接字。在向对方发送消息之前。先在服务器上维护一个Web套接字连接。然后在前端维护一个。再维护Web套接字。

Websocket使用ws或wss协议。对应http或https。在WebSocket远程连接成功后。这是一个全双工的TCP通道。在这个通道上可以无差别的从工作日结束后向客户端发送数据。WebSocket创建的绑定与长HTTP绑定不同。由于长期的地下室还是HTP协议。他还是提出了一个问题。但只是长期保持联系。

为什么可以实现持久连接?

WebSocket协议是由HTML5标准定义的。它最初是为浏览器设计的。避免了相似性的限制。因为浏览器可以和任何工作端进行通信。现代的浏览器大多支持WebSocket。虽然WebSocket最初定义为HTML5。但它同样适用于移动终端。虽然可以通过Socket直接与终端连接。但使用WebSocket可以有效防止一些防火墙的窃听。

WebSocket建立了一个连接。我们称之为持久连接。每个连接都是服务器的一个资源。但是。如果服务器长时间没有消息通信。就会倾向于关闭连接。其实。WebSocket的任务就是及时向桌面端发送空白消息。保证连接不会自动断开。很多网站采用技术实现推送技术。当浏览器向服务器发送HTTTP请求时。在一定的时间间隔内(如1秒)进行轮询。然后服务器将最新的数据返回给客户端的浏览器。这种传统的模式有明显的缺点。那就是浏览器需要不断地访问服务器。但HTTTP请求中会包含一个较长的头。在这个头中。真正有效的数据只能占据一小部分。这似乎造成了很多资源(如带宽)的浪费。

第一次连接到Web套接字时。使用普通的HTTP与服务器通信。与Web套接字交换消息。一旦建立了Web套接字连接。所有的消息都可以通过这个通道发送。同时。客户端和服务器会继续使用乒乓球保持心跳。防止非正常断线。将网站的刷新逻辑移植到支持的浏览器上很容易。只需要找一些webssocket接口使用双webssocket属性即可。因为协议是完全双向的。服务器可以随时主动向客户端发送数据。与HTTP请求相比。接收客户请求的响应所需的延迟要少得多。即使与彗星等长时间的轮询相比。也可以在短时间内更频繁地传输数据。

答案写到这里。我想您应该明白了WebSocket的原理。也知道了WebSocket可以实现持久连接的原因。WebSocket是基于web的一项新技术。它克服了以往HTTP协议下访问速度较慢容易断开连接。网站假死的现象。未来WebSocket技术将全面普及。提高我们的上网体验!

以上便是我的一些见解和回答。可能不能如您所愿。但我真心希望能够对您有所帮助!不清楚的地方您还可以关注我的头条号“每日精彩科技”我将竭尽所知帮助您!

码字不易。感觉写的还行的话。还请点个赞哦!

以上就是由优质生活领域创作者 生活常识网 整理编辑的,如果觉得有帮助欢迎收藏转发~

分享到 :
相关推荐

中秋节就要到了,一人说一句关于中秋节的诗词吧,来个接龙?

请用语音读文章热门回答:天高气爽桂花香。万里河山皆金阳。中秋月圆人团圆。大家齐把[&...

重阳节,有哪些广为传唱的经典诗词?

请用语音读文章热门回答:非常感谢【问答】邀请回答这个问题。最近因一些琐事无暇顾及[&...

白起和岳飞两位顶尖军事统帅,如果各带10万大军对决,谁会赢?为什么?

请用语音读文章热门回答:这个问题如同问“关公战秦琼”一样。其实毫无意义。不过看了[&...

电信卡有哪些比较划算的套餐?

请用语音读文章热门回答:本人专注通信相关问题。解答通信疑惑。➕关注了解更多内容![&...

发表评论

您的电子邮箱地址不会被公开。

评论(2)

  • 风华三生 永久VIP 2022年9月30日 12:41:53

    协议,客户端,服务器,浏览器,通信,持久,通道,数据,消息,服务端

  • 滴蜡泪 永久VIP 2022年9月30日 12:41:53

    没想到大家都对WebSocket是什么原理?为什么可以实现持久连接?感兴趣,不过这这篇解答确实也是太好了

  • 苏梦北 永久VIP 2022年9月30日 12:41:53

    首先需要明白:基于TCP的应用层协议。只要设计者愿意。都是可以实现持久连接的。你问的方式。大概是在和HTTP做比较。