WebSocket简述与网络知识回顾

发布于:2025-09-05 ⋅ 阅读:(17) ⋅ 点赞:(0)

为什么用webSocket?

我们首先来讲webSocket是什么,然后来说他和http的区别,最后来讲为什么用websocket

WebSocket是什么

任何东西的出现都有目的,即为了解决特定的问题。普通的http相当于一问一答,且请求只能由client来发起(“请求只能由 client 发起”是 TCP + HTTP 语义 + 浏览器同源策略的硬性结果,且浏览器无法对外暴露端口,也就无法连接TCP),那么如果服务端想先给client发送信息呢?这样就会导致client必须去轮询,很麻烦。所以我们需要一种双向连接的协议。故有了WebSocket。在具体讲之前,我们先来回顾一下网络

网络知识回顾

这里我想再来说一下有关socket和port的内容,首先来看port,由于我们主机中有多个进程,外部连接时想要连接,则要知道连接我们具体的哪个程序,那么port就相当于门牌号,通过传递port,就知道连接我们主机上的哪个进程,那么怎么知道我们主机在哪呢?通过ip就可以,所以通过ip+port就可以标识特定机器上的特定进程。接下来我们来看socket,如果说port是门牌号,那么socket可以看为大门,数据通过socket来进行从网络到进程的传输,在OS层面,socket就被抽象为了一种file description,而socket下又有TCPSocket,即通过TCP来进行传输。TCP连接的两端可以简单看为TcpSocket的对话。那么好,双方对话的过程中,client需要知道server程序的ip+port,server同时也需要知道client的ip+port,否则如果有多个连接,那么server无法分辨。也就是进行tcp连接的时候,双方需要实现这个图:
主机 A 主机 B
┌----------------------┐ ┌----------------------┐
│ 进程 1 socket fd=3 │───TCP 连接───────→│ 进程 2 socket fd=5 │
│ 本地 192.168.1.10:52341│ │ 本地 10.0.0.5:443 │
└----------------------┘ └----------------------┘
那么好,我们都知道,TCP link是client先发起请求,那么他怎么知道对面(即server)的ip+port呢?他的ip一般是不变的,但是这个port他肯定会变,我们需要给他设定一个对外暴露的端口,来对外提供服务。比如mysql端口就3306,前面说过了,端口只是门牌号,真正数据的传输需要大门,也就是socket,我们的socket就去监听这个端口,如果端口中有信息,那么通过socket拿过来。所以你在server一般可以看到这段代码:

int srv = socket(AF_INET, SOCK_STREAM, 0);
bind(srv, 0.0.0.0:443);   // socket监听对应端口
listen(srv, backlog);
accept(...);              // 等待别人连进来

他对外暴露是为了提供服务,但是这会面临风险,互联网是不安全的,我们的计算机上有很多程序,如果都对外暴露端口,动动你聪明的小脑袋瓜也知道是不可能的。所以我们只会暴露特定的端口,一旦这个端口被暴露,他就不可以被别的程序用了(端口的目的就是标识唯一进程,肯定不可以重复的)。但是server也需要知道client的端口啊,如果client的端口扔给server,不就会client端口导致暴露吗?那么就到我们的OS大显身手的时候了,对于一个TCP 连接,他会给client一个用于这次连接的临时端口,等到连接结束了,那么给他换一下就可以了,然后用一个特定的socket去监听就可以了,你一般会看到这个代码

int cli = socket(AF_INET, SOCK_STREAM, 0);
connect(cli, 服务器IP:443); // 主动“打出去”

这里OS肯定会给这个socket搞一个临时ip+port的。只是对我们透明了而已。所以对于网络连接来说,我们需要知道下面五个信息,便可以标识唯一socket

  • 连接层协议:TCP / UDP
  • 远程IP
  • 远程端口
  • 本机IP
  • 本机端口
    所以对于socket,如果他们中的这五个值不完全相同,那么就OS就可以分辨出对应的TCP数据传输链条,可以分辨对应的socket。所以对于一个port,他可以被多个socket连接(远程IP+port会不同),但是逻辑上来说,去监听一个port,同一时刻只可以有一个socket。这里监听和连接的区别就是,某个socket去监听对应port,如果有对应的连接,那么执行连接。连接上的socket就可以进行TCP传输。前者只处理新的连接,后者则是连接后开始传输对应的数据。这就像NIO,有一个线程只处理新来的连接,后边的线程才去处理连接后的数据(比如读,写)这里只是类比,但是大体思路差不多。

既然讲到了IO,那么我们来说说IO 多路复用。简单来说,由于OS出色的抽象能力,出现了fd这个东西(这也是为什么java要用接口),IO 多路复用就是用一个线程管理多个fd,这里fd可以是文件,可以是pipe,可以是socket,这就是抽象的强大之处。从最开始select的应用层轮询,到后边epoll的kernel事件触发。多路复用使得一个线程就可以管理多个fd的操作。这就像客服,他只在收到消息的时候去处理对应的消息,而不是给每个用户都配备一个客服,每个客服都去等待用户的消息。

回到WebSocket

前文说到浏览器无法对外暴露端口,因为如果暴露了,那么就相当于给坏人敞开大门了。且web去连接Server给的端口也是临时端口。那么我们又有了相关的需求,怎么办呢?WebSocket就来了,你看这里的Web和这里的Socket,他的目的就是让运行在浏览器里的脚本,能够像直接拿着一个 TCP socket 那样,随时双向收发数据,而不必再受 HTTP 请求-应答模型的限制 。他也是基于TCP协议,是和HTTP同等抽象概念的应用层协议。对TCP做了更强的增强。毕竟我们网络就是基于简单但是强大的底层来实现功能多样,安全的上层。


网站公告

今日签到

点亮在社区的每一天
去签到