Socket && WebSocket
文章目录
一般网络编程
都叫Socket编程
,网络编程通常采用的是经典的客户端-服务器模型(CS 模型)。
网络编程无非简单来看就是 TCP编程 和 UDP编程。
Socket
每一次建立 socket 连接后,都会生成一个 SessionId,便于标识通讯中的客户端和服务端。(SessionId 应保证分布式唯一)
socket 简介
Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口。
在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面,对用户来说,一组简单的接口就是全部,让 Socket 去组织数据,以符合指定的协议。
套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。 套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。 网络套接字是IP地址与端口的组合。
阮一峰老师曾讲到:socket就是插座。服务器的socket,就是服务器提供插座,等着客户端的插头插进来。一旦插入完成,服务器-客户端的通信就建立了。
socket 作用
socket(套接字)作用:就是应用层获取传输层的协议,是应用层和传输层沟通的桥梁。
socket 类型
常用的 Socket 类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。
- 流式,二进制流,是一种面向连接的 Socket,针对于面向连接的 TCP 服务应用。应用场景:im 通讯,安全
- 数据报式 Socket 是一种无连接的 Socket,对应于无连接的 UDP 服务应用。应用场景:短信、视频直播,传输速度快
简单对比一下
- TCP:比较靠谱,面向连接,安全,可靠的传输方式 ,但是比较慢
- UDP:不是太靠谱,不可靠的,丢包不会重传,但是比较快
CS 模型
c: client,s: server
WebSocket
简介
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
实现思路
- 监听:首先要挂起一个进程来监听来自客户端的请求
- 握手:对于第一次合法的请求,发送合法的header回去
- 保持连接:有新消息到了就广播出去。直到客户端断开
- 接受另一个请求,重复2和3
特性
- 建立在 TCP 连接之上
- 较少的控制开销
- 更强的实时性
- 保持连接状态
- 可以发送文本、二进制数据
- 没有同源限制
连接过程
websocket 的连接还是比较简单的,只要进行 一次握手,就可以进行后续的通讯了,这里分为三步:
- http get 请求将 http 请求升级为 websocket 请求
- 数据通讯
- 断开链接(可由任一方中断)
握手协议
在第一步的时候进行了握手,这里来看一下请求的详情。
客户端使用 http 请求升级切换到 Websocket 协议
|
|
|
|
帧格式
WebSocket协议使用帧(Frame)收发数据【帧,听不懂?就是比特位!一位二进制数就是一比特位。值只有0和1,一字节是8比特位】
客户端发送给服务端的帧必须通过4字节的掩码(Masking-key)加密,服务端收到消息后,用掩码对数据帧的Payload Data进行异或运算解码得到数据,如果服务端收到未经掩码加密的数据帧,则应该马上关闭该WebSocket。
服务端发给客户端的数据则不需要掩码加密,客户端如果收到了服务端的掩码加密的数据,则也必须关闭它。
上图为websocket的帧格式,下面我们一个个来分析 这里从左往右看,横向为32位(bit)
- FIN:最后的片段
- RSV1-3:拓展定义
- opcode:帧类型,其中控制帧:0x8 (Close), 0x9 (Ping), and 0xA (Pong),数据帧主要有:0x1 (Text), 0x2 (Binary)
- MASK:数据是否掩码
- Payload len:负载长度
- Extended payload length:拓展负载长度
- Masking-key:掩码
- Playload Data:负载数据
所以,websocket传递数据时最小的请求头为 FIN+RSV1-3+opcode+MASK+Payload len+Masking-key = 6 byte(字节),剩下的就都是实际数据,相比于http头部小得多。
websocket前后端通信的时候,丢包怎么处理,怎么监控
todo: 待研究
- 集群部署聊天(实现横向可扩展)
- 采用消息确认机制,确认消息稳定的送达
socket.io
概览
socket.io 本身是一个 Node.js 的包,使用 long polling 或者 websocket 的方式提供持续的网络连接服务。由于简单好用,很多开发者为其开发了不同语言的 SDK,比如 Java、C++、Go 等。
go-socket.io Golang版后端 socket.io 的实现框架。
socket.io 优势
socket.io 会自动选择合适双向通信协议,仅仅需要程序员对套接字的概念有所了解。
socket.io 劣势
socket.io并不是一个基本的、独立的、能够回退到其它实时协议的WebSocket库,它实际上是一个依赖于其它实时传输协议的自定义实时传输协议
的实现。该协议的协商部分使得支持标准WebSocket的客户端
不能直接连接到Socket.io服务器,并且支持Socket.io的客户端也不能与非Socket.io框架的WebSocket或Comet服务器通信。因而,Socket.io要求客户端与服务器端均须使用该框架。
github.com/googollee/go-socket.io
WebSocket第三方框架,基于开源项目 github.com/gorilla/websocket 开发的。客户端代码只能用 socket.io 框架,这样就会存在 go-socket.io 与 socket.io 的兼容性问题。
github.com/googollee/go-socket.io@v1.6.1 内存泄漏问题:
- 原因:由于v1.6.1版本的session未回收,断连socket conn存在内存中,导致内存不断上升。
- 解决:在v1.6.2版本修复,socket连接断开回收该链接。Session. Remove(sid)
- 结果:目前系统socketio已经稳定1w连接/1G内存
概念
-
namespace 和 room 是同一个服务端socket多路复用的体现。
namespace、room 和 socket 的关系为:socket会属于某一个room,如果没有指定,那么会有一个default的room。这个room又会属于某个namespace,如果没有指定,那么就是默认的namespace /.
-
Adapter:适配器是一个服务器端的组件,负责将事件广播给所有或一个子集的客户端。
Socket 与 WebSocket 的区别
本质上来讲,两者并没有什么关联,只是名称类似、作用类似而已!【两者都能做即时通讯】
- Socket 是位于应用层和传输控制层之间的一组接口,用户可以通过 Socket 来操作底层 TCP/IP 协议族通信。而 WebSocket 是一个完整的应用层协议。(相比WebSocket,Socket更底层)
- Socket 使用 TCP 协议,WebSocket 使用 WebSocket 协议。
- 建立持久性连接时,Socket 需要三次握手,WebSocket 只需要一次握手。
- WebSocket需要处理跨域问题,Socket则不需要。
WebSocket 与 HTTP 的关系
相同点 1. 都是一样基于TCP的,都是可靠性传输协议。 2. 都是应用层协议。 不同点 1. WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。 2. WebSocket是需要握手进行建立连接的。 联系 WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。