onlyliuxin / coding2017

218 stars 643 forks source link

为什么不直接使用socket ,还要定义一个新的websocket 的呢? #497

Open onlyliuxin opened 7 years ago

leonindy commented 7 years ago

避开业务需求而直接谈技术选型,都是耍流氓:D

首先澄清一点,Socket与WebSocket处于的网络层级是不对等的,很难直接比较。WebSocket在网络七层协议上的层级等同于Http,而Socket位置处于七层协议中的第四层,Socket是操作系统对TCP、UDP的封装。WebSocket处在上层,Socket处在下层,WebSocket依赖于Socket,Socket为WebSocket服务。

那么应该是拿WebSocket与Http进行比较。WebSocket常见于客户端-服务端全双工的场景,客户端可以发送消息给服务端,同时服务端也可以主动发送消息给客户端。而Http是单向的关系。只能客户端发送请求,服务端被动接收,服务端没有主动发起对话的能力。

聊天是一个典型的全双工场景:聊天的双方先将消息发送给服务端,服务端在把消息转给对方。如果使用WebSocket,得益于全双工,整个逻辑非常顺畅。而Http场景下,服务端没有主动发起请求的能力,只能维持Http长链接,或者客户端定时轮询服务端,获取最新的信息。

不过WebSocket并不普及。完整的WebSocket通信,需要客户端(浏览器)、服务端、网关节点、防火墙等一套的支持。尤其对于面向用户的环境来说,用户使用的浏览器、用户所处的网络环境,都是不能控制的。这种情况下建议不要使用WebSocket。

最后,如果迫不及待的想使用WebSocket,可以考虑使用SocketJS+SpringMVC+Tomcat8。SocketJS提高了通信的成功率:若是环境不支持WebSocket,就会采用XAR流等备选方案通信。SpringMVC也有对SocketJS的支持。

wubingyang commented 7 years ago

可以把WebSocket想象成HTTP,HTTP和Socket什么关系,WebSocket和Socket就是什么关系。

Socket是一个便于使用 TCP/UDP 的接口规范, WebSocket是一个应用层协议..

就像巴基斯坦和卡巴斯基一样有基巴关系

lanyuanxiaoyao commented 7 years ago

哈哈首先自己的博客先吹一波:http://lanyuanxiaoyao.com 买不了吃亏买不了上当

首先,要说到这个websocket和socket,umm,只让我和大家一样不约而同地想到一个图:

哈哈哈哈,反正他们之间是没什么直接的联系单的,既然要说区别,就让我们先来理一理这两个东西是个什么玩意儿先。

Websocket

WebSocket一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket通讯协定于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。WebSocket API也被W3C定为标准。
  WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以建立持久性的连接,并进行双向数据传输。  
——维基百科

以上是对Websocket的一个简单的介绍,其实从上面加粗的关键词就可以看出Websocket的一些特点:持久连接,双向数据传输……
可能我们没有对网络传输有一个系统的概念,那么我们先描述一下在Websocket之前我们是怎么进行网络数据传输的

没有Websocket的时代

显然我们寻常的网站都是使用HTTP协议进行通信的,那么相比较Websocket,HTTP最大的缺点是什么呢?那就是——请求只能由客户端发起,这是一种什么情况呢,就是每次都是客户端向服务端请求信息,然后服务器回传信息,但是服务器不能主动向客户端发送信息,让我们想象一下两个人说话
客户端:“嘿!服务器你吃了吗?”
服务器:“吃了!吃了!”
客户端(心想):“原来服务器酱已经吃过了”(捂住耳朵)
服务器:“嘿!我们一起出去玩吧!”
客户端:“听不见,听不见……”
服务器:“嘿!我们一起出去玩吧!”
客户端:“听不见,听不见……”
服务器:“欸~ 我们一起出去玩吧,你怎么都不理我了……”(委屈哭)
客户端:“听不见,听不见……”
这种单向的消息传递在平常是没有问题的,因为服务器就像一个客服一样,只有当我们有问题去问它的时候,它才会告诉我们答案,然后平常客服是没有办法主动打扰我们,但是在有的场景却并不是这么简单,比如在线聊天和在线游戏,当我们服务端发生了连续的变化,而且这种变化不是由客户端引起的,那么服务器也没有办法通知客户端发生了何种变化,除非客户端主动来问(发起请求)
在这种情况下,客户端该如何保持和服务器的联系呢?我们有一个简单的方式:轮询
顾名思义,就是客户端像一个车轮一样不断重复向服务器发起请求,询问有没有发生变化,但是我们也可以想到,这种方式是有很多缺点的

  1. 服务器消耗资源大
    为了应付我们客户端的轮询,HTTP连接必须不断打开关闭,或者一直保持打开的状态,即使服务器的状态没有发生变化,我们客户端这边的资源也会一直被占用,没有办法被释放
  2. 效率低下
    可以想象得到,其实在轮询中我们获得的有效信息占有的部分是非常小的,有可能我们一整天数据才发生一次变化,但是为了获得这个变化,却不得不一整天都在对服务器进行轮询,效率非常低
  3. 网络压力大
    我们都知道HTTP请求是包含着各种头部信息的,这就意味着,即使我们的请求里面没有任何信息,一个HTTP也要有好几百B的数据量,似乎并不大,但是如果在高并发的状况下进行轮询,那么网络中的流量可就非常庞大了,而且这些流量都是无用的

Websocket的时代

显然我们现有的网络协议都不能解决这个服务器主动发起通信的问题,那么!我们来写一个新的协议吧!
于是,Websocket协议就在2011年被正式提出来了,并且迅速被所有浏览器都支持了,因为这个功能贼好用啊!在网络中服务端和客户端终于可以进行平等通信了,情况就变成了
客户端:“嘿!服务器你吃了吗?”
服务器:“吃了!吃了!”
服务器:“嘿!我们一起出去玩吧!”
客户端:“好啊!好啊!”
这个变化可以用一张图来表示

Websocket的优点

虽然有一堆乱七八糟的特点,但是最重要的一点就是解决了服务器主动向客户端下发消息这个问题
值得注意的一点是,Websocket和HTTP是同级的协议,都是基于TCP协议的应用层协议,也就是说不存在说HTTP协议包含Websocket协议这种说法,但是这也不是说这两个协议之间毫无关系,因为Websocket在服务器主动发起请求的时候,采用的是HTTP协议来进行握手,一旦握手成功,Websocket就转而运行在TCP协议之上的,就和HTTP协议没有关系了

Socket

Socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力。 ——百度百科

Socket是一套API接口,是建立在TCP和应用程序之间的一个抽象层,就是我们之前说的“面向抽象编程”的这个抽象,Socket这个抽象层帮我们封装了TCP/UDP等网络协议的操作,让我们可以通过Socket提供的接口进行网络通信,可以通过一个图来说明这个抽象的功能

然后我们就可以简单得使用Socket的API进行通信操作了,当然,我们是不用管下面TCP具体是怎么实现的

关于Socket的起源
Socket起源于UNIX,在Unix一切皆文件哲学的思想下,Socket是一种"打开—读/写—关闭"模式的实现,服务器和客户端各自维护一个"文件",在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件

对比

让我们把目光放回Websocket和Socket的关系上来,当然结论我们已经知道了,就是这俩家伙没有什么关系,Websocket是一种应用层协议,Socket是封装了网络层操作的抽象API接口,如果非要说他们有什么关系的话,那么除了名字比较像之外,应该就是理念差不多了吧

参考

  1. 维基百科-WebSocket
  2. 阮一峰-WebSocket 教程
  3. Socket 与 WebSocket
  4. WebSocket 是什么原理?为什么可以实现持久连接?
  5. WebSocket和Socket的区别
onlyliuxin commented 7 years ago

很多答案都跑题了, 这个问题的本身不是问socket和websocket的区别, 而是为什么浏览器不能直接和服务器进行socket通信, 还要在应用层搞一个新协议呢?

littledog623 commented 6 years ago

感觉是因为Socket实现的是TCP,而TCP是面向stream传输的,直接用Socket容易出问题,比如粘包问题。WebSocket是一个应用层协议,更抽象,不需要考虑这些问题。所以当然可以直接用Socket实现长连接,不过仍然需要实现自己的上层协议来处理分包,比较麻烦,不如直接用WebSocket。自己的客户端使用自己的私有协议还行,但浏览器的话更需要一个统一的应用层协议,所以WebSocket就出现了。

eightHundreds commented 5 years ago

那么在WebSocket之前,应用层有没有其他的全双工协议?为什么不用他们?

vickwv commented 5 years ago

很多答案都跑题了, 这个问题的本身不是问socket和websocket的区别, 而是为什么浏览器不能直接和服务器进行socket通信, 还要在应用层搞一个新协议呢?

所以您知道为什么吗?

imfantuan commented 5 years ago

一群不懂装懂的人在网上瞎抄答案。。。

大致概念:

  1. TCP/IP 协议,是网络七层协议的第四层,本身没有长连接或短连接的区别;
  2. HTTP 是基于 TCP 协议之上的「短连接」应用层协议,它的出现极大简化了网络应用的实现门槛,丰富了应用;
  3. Socket 是操作系统内置的一套操作 TCP/IP 协议的网络(套接字)的方法;
  4. Websocket 是跟 HTTP 对应的,基于 TCP 协议之上的「长连接」协议。

问 & 答

问:为什么在 HTTP 存在的很长一段时间都没有出现标准的「长连接」协议呢?

答:因为直接基于 TCP 的握手协议根本不分长短连接,所以你可以理解成天生就是长连接。所以很早就有基于长连接的「聊天协议」专门用于聊天等碎片化信息交换场景(例如 IRC、XMPP)。随着 WWW(万维网)被发明出来,需要一个交换丰富表达形式的方式,来表达一些中等长度的内容展现。与 IRC 那种 为少数人之间传递碎片信息的协议不一样,WWW 被设计成 1对上万人甚至数十万人传递信息,所以需要一个能节省「连接维系成本」的协议,它需要在用户看完这篇内容后,断开连接,以给其他人再查看这篇内容,于是就出现了 HTTP 短连接协议。所以,并不是在 HTTP 之前没有 长连接协议,只是他们在当时应用场景范围不大。

问:QQ、微信基于的都是 IRC 协议吗?

答:不是,QQ、微信基于自己的私有通信协议,为什么呢?因为聊天是碎片化的实时行为,场景是高频地进行网络交换。所以这种情况下,节省 TCP 的握手次数、节省协议本身的网络消耗就显得非常重要。所以大型 IM 软件都基于私有协议(有自己的服务端、客户端),这样能最大化精简交换信息时消耗的网络资,而 HTTP 的特点是「每进行一次网络交换,都能传送一篇长文,供读者读好一段时间」,并非高频交换,所以从协议设计的角度来讲,「统一性、功能性」比「简洁性」更重要)。

问:为什么再需要 Websocket,而不能直接使用以前的 IRC或 XMPP 呢?

答:因为 浏览器是基于 HTTP 的标准客户端,而且 HTTP 协议发展到今天在各个方面已经非常成熟,所以最大程度复用是合理的。

问:QQ、微信 会改成 Websocket 协议吗?

答:Web 版本可能会,但客户端版本很大概率不会。原因很简单,就是前面说的,公用协议臃肿,既然有自己的客户端,为什么不自己设计协议。但很多创业产品,应该会直接使用 Websocket 来 startup,因为普及,所以开发门槛低。

问:既然 Websocket 臃肿,为什么各个产品不在 Web 里使用私有协议?

答:因为整个浏览器都不支持直接调用系统底层的 Socket,基于浏览器的 Web 自然无法调用,只能使用封装的高级协议方案 —— Websocket。

vickwv commented 5 years ago

一群不懂装懂的人在网上瞎抄答案。。。

大致概念:

  1. TCP/IP 协议,是网络七层协议的第四层,本身没有长连接或短连接的区别;
  2. HTTP 是基于 TCP 协议之上的「短连接」应用层协议,它的出现极大简化了网络应用的实现门槛,丰富了应用;
  3. Socket 是操作系统内置的一套操作 TCP/IP 协议的网络(套接字)的方法;
  4. Websocket 是跟 HTTP 对应的,基于 TCP 协议之上的「长连接」协议。

问 & 答

问:为什么在 HTTP 存在的很长一段时间都没有出现标准的「长连接」协议呢?

答:因为直接基于 TCP 的握手协议根本不分长短连接,所以你可以理解成天生就是长连接。所以很早就有基于长连接的「聊天协议」专门用于聊天等碎片化信息交换场景(例如 IRC、XMPP)。随着 WWW(万维网)被发明出来,需要一个交换丰富表达形式的方式,来表达一些中等长度的内容展现。与 IRC 那种 为少数人之间传递碎片信息的协议不一样,WWW 被设计成 1对上万人甚至数十万人传递信息,所以需要一个能节省「连接维系成本」的协议,它需要在用户看完这篇内容后,断开连接,以给其他人再查看这篇内容,于是就出现了 HTTP 短连接协议。所以,并不是在 HTTP 之前没有 长连接协议,只是他们在当时应用场景范围不大。

问:QQ、微信基于的都是 IRC 协议吗?

答:不是,QQ、微信基于自己的私有通信协议,为什么呢?因为聊天是碎片化的实时行为,场景是高频地进行网络交换。所以这种情况下,节省 TCP 的握手次数、节省协议本身的网络消耗就显得非常重要。所以大型 IM 软件都基于私有协议(有自己的服务端、客户端),这样能最大化精简交换信息时消耗的网络资,而 HTTP 的特点是「每进行一次网络交换,都能传送一篇长文,供读者读好一段时间」,并非高频交换,所以从协议设计的角度来讲,「统一性、功能性」比「简洁性」更重要)。

问:为什么再需要 Websocket,而不能直接使用以前的 IRC或 XMPP 呢?

答:因为 浏览器是基于 HTTP 的标准客户端,而且 HTTP 协议发展到今天在各个方面已经非常成熟,所以最大程度复用是合理的。

问:QQ、微信 会改成 Websocket 协议吗?

答:Web 版本可能会,但客户端版本很大概率不会。原因很简单,就是前面说的,公用协议臃肿,既然有自己的客户端,为什么不自己设计协议。但很多创业产品,应该会直接使用 Websocket 来 startup,因为普及,所以开发门槛低。

问:既然 Websocket 臃肿,为什么各个产品不在 Web 里使用私有协议?

答:因为整个浏览器都不支持直接调用系统底层的 Socket,基于浏览器的 Web 自然无法调用,只能使用封装的高级协议方案 —— Websocket。

谢谢!!!懂了!

Kila2 commented 4 years ago

器都不支持直接调用系统底层的 Socket,基于浏览器的 Web 自然无法调用,只能使用封装的高级协议方案 —— Websocket。

能转载吗?

fengsheng-v commented 3 years ago

https://github.com/onlyliuxin/coding2017/issues/497#issuecomment-491731378

因为整个浏览器都不支持直接调用系统底层的 Socket,基于浏览器的 Web 自然无法调用,只能使用封装的高级协议方案 —— Websocket。

--这个才是正解

cyrto commented 3 years ago

大部分浏览器不支持直接使用Socket,是出于安全因素考虑,因为浏览器只是一个沙箱环境,如果可以直接通过操作比较底层的Socket协议,允许直接通过浏览器创建和访问原始套接字,实际上提供了一种绕过防火墙的方法。之前机器上侦听环回网络套接字的每项服务,无法被外部攻击者访问,但现在都可以从浏览器进行攻击。网络上的每台机器,通常通过网关和防火墙与 Internet 隔离,现在都可以被 Internet 代码访问或攻击。

还有其他原因。当浏览器无需插件即可执行端口扫描和 DDOS 攻击时,端口扫描和 DDOS 攻击变得更加容易(是的,浏览器可以尝试在 HTTP(S) 服务器上启动 DDOS,但使用较低级别的套接字可能会更有效率)。网络蠕虫(尤其是那些只有一小部分机器容易受到攻击的蠕虫)可以在每个在流行网站上查看广告的人开始发送攻击时传播得更快,而不仅仅是那些真正被感染的人。

再加上大部分的浏览器没有为JavaScript实现这样的raw socket api(基于V8引擎的Nodejs支持原始的Socket编程) 不过也有一些在客户端JavaScript 中实现原始套接字 api 的草案,比如:

https://www.w3.org/TR/raw-sockets/ https://developer.mozilla.org/en-US/docs/Web/API/TCPSocket

Chrome通过扩展程序的形式在其API 中支持原始 TCP 和 UDP 套接字(deprecated),参考:https://developer.chrome.com/docs/extensions/reference/socket

一些开发人员已经在使用它创建有趣的项目,例如这个 IRC 客户端 要访问此 API,需要引入相关扩展程序的清单。使用套接字非常简单,例如:

chrome.socket.create('tcp', '127.0.0.1', 8080, function(socketInfo) {
  chrome.socket.connect(socketInfo.socketId, function (result) {
        chrome.socket.write(socketInfo.socketId, "Hello, world!");         
    });
});

参考链接:

https://stackoverflow.com/questions/12407778/connecting-to-tcp-socket-from-browser-using-javascript https://stackoverflow.com/questions/10902256/possible-web-protocols-in-javascript

HomyeeKing commented 3 years ago

Socket 断了 上层的websocket是不是也就断了

gonyua commented 3 years ago

一群不懂装懂的人在网上瞎抄答案。。。

大致概念:

  1. TCP/IP 协议,是网络七层协议的第四层,本身没有长连接或短连接的区别;
  2. HTTP 是基于 TCP 协议之上的「短连接」应用层协议,它的出现极大简化了网络应用的实现门槛,丰富了应用;
  3. Socket 是操作系统内置的一套操作 TCP/IP 协议的网络(套接字)的方法;
  4. Websocket 是跟 HTTP 对应的,基于 TCP 协议之上的「长连接」协议。

问 & 答

问:为什么在 HTTP 存在的很长一段时间都没有出现标准的「长连接」协议呢?

答:因为直接基于 TCP 的握手协议根本不分长短连接,所以你可以理解成天生就是长连接。所以很早就有基于长连接的「聊天协议」专门用于聊天等碎片化信息交换场景(例如 IRC、XMPP)。随着 WWW(万维网)被发明出来,需要一个交换丰富表达形式的方式,来表达一些中等长度的内容展现。与 IRC 那种 为少数人之间传递碎片信息的协议不一样,WWW 被设计成 1对上万人甚至数十万人传递信息,所以需要一个能节省「连接维系成本」的协议,它需要在用户看完这篇内容后,断开连接,以给其他人再查看这篇内容,于是就出现了 HTTP 短连接协议。所以,并不是在 HTTP 之前没有 长连接协议,只是他们在当时应用场景范围不大。

问:QQ、微信基于的都是 IRC 协议吗?

答:不是,QQ、微信基于自己的私有通信协议,为什么呢?因为聊天是碎片化的实时行为,场景是高频地进行网络交换。所以这种情况下,节省 TCP 的握手次数、节省协议本身的网络消耗就显得非常重要。所以大型 IM 软件都基于私有协议(有自己的服务端、客户端),这样能最大化精简交换信息时消耗的网络资,而 HTTP 的特点是「每进行一次网络交换,都能传送一篇长文,供读者读好一段时间」,并非高频交换,所以从协议设计的角度来讲,「统一性、功能性」比「简洁性」更重要)。

问:为什么再需要 Websocket,而不能直接使用以前的 IRC或 XMPP 呢?

答:因为 浏览器是基于 HTTP 的标准客户端,而且 HTTP 协议发展到今天在各个方面已经非常成熟,所以最大程度复用是合理的。

问:QQ、微信 会改成 Websocket 协议吗?

答:Web 版本可能会,但客户端版本很大概率不会。原因很简单,就是前面说的,公用协议臃肿,既然有自己的客户端,为什么不自己设计协议。但很多创业产品,应该会直接使用 Websocket 来 startup,因为普及,所以开发门槛低。

问:既然 Websocket 臃肿,为什么各个产品不在 Web 里使用私有协议?

答:因为整个浏览器都不支持直接调用系统底层的 Socket,基于浏览器的 Web 自然无法调用,只能使用封装的高级协议方案 —— Websocket。

你好,问下websocket和socket分别在什么项目场景下用。还有一点不理解scoket是封装与tcp之上,websocket应该也是基于tcp之上实现的即时通信,websocket还能支持网页为什么现在还要用socket实现即时通讯呢?求教