OSI & TCP/IP 模型
要弄清 tcp udp socket http websocket 之间的关系,首先要知道经典的OSI七层模型,与之对应的是TCP/IP的四层模型。
从图中可以看出,tcp udp 工作在传输层,http websocket 工作在应用层,而 socket 不属于七层模型中的任一层,可以理解为socket工作在传输层与应用层中间的隐含层中。
几者之间的关系
socket 本身不是一种协议,而是对传输层中的 TCP/UDP 协议进行了封装,对用户隐藏了内部 TCP/UDP 是如何传输的,只提供一套接口(API)给程序员调用,从而完成socket编程。
通过socket接口,我们才能使用TCP/UDP协议。
而我们通常浏览网页用到的 http 协议,是建立在TCP协议之上的一种应用层协议。 http协议最显著的特点是它是一种无状态连接,客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接,是一种“短连接”。
对于几者之间的关系,可以概况为:
http websocket 等应用层协议通过 socket 接口从而调用 tcp udp 等传输层协议,从而达到网络通信。
tcp udp => socket => http websocket
综上所述,我们编程不会直接去调用tcp udp,而是通过他们封装好的接口socket去通信。可以说,现在几乎网络上所有的通信,底层都是通过socket完成的,一切皆Socket。
HTTP
HTTP是基于TCP协议的应用的超文本传输协议,属于应用层的协议。请求时需建立TCP连接,请求结束后断开连接,完成一次请求/响应操作。
HTTP协议永远都是客户端发起请求,服务器回送响应,这样就限制了使用HTTP协议,无法实现在客户端没有发起请求的时候,服务器将消息推送给客户端。
HTTP协议是一个无状态的协议,同一个客户端的这次请求和上次请求是没有对应关系。
优点:基于应用级的接口使用方便
缺点: (1)传输速度慢,数据包大。 (2)如实现实时交互,服务器性能压力大。 (3)数据传输安全性差
注意:服务器不会主动给客户端发送数据。
Socket
Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API)
Socket连接需要一对套接字,一个运行于客户端,另一个运行于服务端!之间的连接分为三个步骤:服务器监听,客户端请求,连接确认。
(1)服务器监听:是服务端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
(2)客户端请求:是由客户端的套接字提出连接请求,要连接的目标是服务端的套接字。所以客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
(3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
WebSocket
虽然叫WebSocket,但它与Socket没有任何关系。就好比:Java与JavaScript,雷锋与雷峰塔,印度与印度尼西亚,黑客与博客的关系,两者没有任何关系!
WebSocket也是一种协议,并且也是基于TCP协议的。可以理解为WebSocket是HTTP的优化,但WebSocket不仅仅在Web应用程序上得到支持。
WebSocket虽然是Html5的产物,但也不仅仅局限于浏览器的应用程序,许多语言都提供了WebSocket的支持,比如C,C++,Python等
webSocket 概念
在WebSocket概念出来之前,如果页面要不停地显示最新的价格,那么必须不停地刷新页面,或者用一段js代码每隔几秒钟发消息询问服务器数据。
而使用WebSocket技术之后,当服务器有了新的数据,会主动通知浏览器。 如当服务端有新的比特币价格之后,浏览器立马接收到消息。
webSocket 优点
1、节约带宽。不停地轮询服务端数据这种方式,使用的是http协议,head信息很大,有效数据占比低, 而使用WebSocket方式,头信息很小,有效数据占比高。
2、无浪费。 轮询方式有可能轮询10次,才碰到服务端数据更新,那么前9次都白轮询了,因为没有拿到变化的数据。 而WebSocket是由服务器主动回发,来的都是新数据。
3、实时性,考虑到服务器压力,使用轮询方式不可能很短的时间间隔,否则服务器压力太多,所以轮询时间间隔都比较长,好几秒,设置十几秒。 而WebSocket是由服务器主动推送过来,实时性是最高的。
Websocket 的作用
在讲Websocket之前,我就顺带着讲下 long poll 和 ajax 轮询 的原理。
ajax轮询
首先是 ajax轮询 ,ajax轮询 的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。
场景再现: 客户端:啦啦啦,有没有新信息(Request) 服务端:没有(Response) 客户端:啦啦啦,有没有新信息(Request) 服务端:没有。。(Response) 客户端:啦啦啦,有没有新信息(Request) 服务端:你好烦啊,没有啊。。(Response) 客户端:啦啦啦,有没有新消息(Request) 服务端:好啦好啦,有啦给你。(Response) 客户端:啦啦啦,有没有新消息(Request) 服务端:…没…没…没有(Response) ---- loop
long poll
long poll 其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。
场景再现 客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) 服务端:额… 等待到有消息的时候…来 给你(Response) 客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop
从上面可以看出其实这两种方式,都是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协议的另外一个特点,被动性 。
何为被动性呢,其实就是,服务端不能主动联系客户端,只能有客户端发起。
从上面很容易看出来,不管怎么样,上面这两种都是非常消耗资源的。
ajax轮询 需要服务器有很快的处理速度和资源。(速度) long poll 需要有很高的并发,也就是说同时接待客户的能力。(场地大小)
所以ajax轮询 和long poll 都有可能发生这种情况。
客户端:啦啦啦啦,有新信息么? 服务端:月线正忙,请稍后再试(503 Server Unavailable) 客户端:…好吧,啦啦啦,有新信息么? 服务端:月线正忙,请稍后再试(503 Server Unavailable)
通俗的说就是,服务器因为每天要接待太多客户了,是个健忘鬼 ,你一挂电话,他就把你的东西全忘光了,把你的东西全丢掉了。
你第二次还得再告诉服务器一遍。
Websocket
Websocket出现了,他解决了HTTP的这几个难题。
首先,被动性,当服务器完成协议升级后(HTTP->Websocket),服务端就可以主动推送信息给客户端啦。
所以上面的情景可以做如下修改。
客户端:啦啦啦,我要建立Websocket协议,需要的服务:chat,Websocket协议版本:17(HTTP Request)
服务端:ok,确认,已升级为Websocket协议(HTTP Protocols Switched) 客户端:麻烦你有信息的时候推送给我噢。。 服务端:ok,有的时候会告诉你的。 服务端:balabalabalabala 服务端:balabalabalabala 服务端:哈哈哈哈哈啊哈哈哈哈 服务端:笑死我了哈哈哈哈哈哈哈
就变成了这样,只需要经过一次HTTP请求,就可以做到源源不断的信息传送了。(在程序设计中,这种设计叫做回调,即:你有信息了再来通知我,而不是我傻乎乎的每次跑来问你) 这样的协议解决了上面同步有延迟,而且还非常消耗资源的这种情况。
他解决了HTTP的被动性,当服务器完成协议升级后(HTTP->Websocket),服务端就可以主动推送信息给客户端啦。
TCP三次握手
所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。
三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在 Socket 编程中,客户端执行connect()时。将触发三次握手。
首先了解一下几个标志:
- SYN(synchronous)同步标志
- ACK (Acknowledgement)即确认标志
- seq应该是Sequence Number,序列号的意思
- 另外还有四次握手的
fin ,应该是 final ,表示结束标志。
|