时间:2023-01-06 09:04:35 | 栏目:Golang | 点击:次
日常工作中,在不刷新页面的情况下发送消息并获得即时响应是我们认为理所当然的事情。但在过去,启用实时功能对开发人员来说是一个真正的挑战。开发者社区从 HTTP 长轮询和 AJAX 走过了漫长的道路,终于找到了构建真正实时应用程序的解决方案。
这个解决方案以 WebSockets 的形式出现,它可以在用户的浏览器和服务器之间打开一个交互式会话。 WebSockets 允许浏览器向服务器发送消息并接收事件驱动的响应,而无需轮询服务器以获取回复。
目前,WebSockets
是构建实时应用程序的第一大解决方案:在线游戏、即时通讯、跟踪应用程序等。
本文将解释 WebSockets
的运作方式,然后使用 Go 语言构建一个简单的 WebSocket 应用程序。
简而言之,WebSocket是一种 Web 技术,可以通过持久的单个套接字连接实现客户端和服务器之间的双向,全双工通信。WebSocket 是为 Web 应用程序开发人员提供基本上是一个接近原始的TCP通信层。
WebSocket 连接以 HTTP 请求/响应握手启动。如果此初始握手成功,则客户端和服务器已同意使用为 HTTP 请求作为 WebSocket 连接建立的现有 TCP / IP 连接。只要需要一旦 WebSocket 连接服务了它的目的,它可以通过关闭握手终止,客户端和服务器都可以启动。
WebSockets 标志着 Web 开发的转折点。直到 WebSockets 的出现,实时网络难以实现和慢于我们习惯于现在;它是通过使用像 Ajax 和 Comet? ?(长)轮询??的技术提供的技术,这些轮询没有真正优化用于实时应用。
WebSocket 技术具有广泛的适用性。您可以在不同的目的中使用它,例如后端服务之间的流数据,或者通过长期的全双工连接连接前端。简而言之,WebSockets 是架构事件驱动的系统和构建实时应用程序和服务的绝佳选择,在那里它必须随时随地提供数据所必需的数据。
我们可以将 WebSocket 用例大致分为两个不同的类别:
网络套接字,或简称为套接字,用作在同一台计算机或同一网络上不同计算机上运行的应用程序之间交换数据的内部端点。
套接字是基于 Unix 和 Windows 的操作系统的关键部分,它们使开发人员更容易创建支持网络的软件。应用程序开发人员可以在他们的程序中包含套接字,而不是从头开始构建网络连接。由于网络套接字用于多种网络协议(HTTP、FTP 等),因此可以同时使用多个套接字。
套接字是由套接字的应用程序编程接口 (API) 定义的一组函数调用创建和使用的。
有几种类型的网络套接字:
每个网络套接字由地址标识,地址是传输协议、IP 地址和端口号的三元组。
主机之间的通信主要有两种协议:TCP 和 UDP。让我们看看您的应用程序如何连接到 TCP 和 UDP 套接字。
为了建立 TCP 连接,Go 客户端使用 net 包中的 DialTCP 函数。 DialTCP 返回一个 TCPConn 对象。建立连接后,客户端和服务器开始交换数据:客户端通过 TCPConn 对象向服务器发送请求,服务器解析请求并发送响应,TCPConn 对象接收服务器的响应。
此连接保持有效,直到客户端或服务器关闭它。创建连接的函数如下:
客户端代码:
// init tcpAddr, err := net.ResolveTCPAddr(resolver, serverAddr) if err != nil { // handle error } conn, err := net.DialTCP(network, nil, tcpAddr) if err != nil { // handle error } // send message _, err = conn.Write({message}) if err != nil { // handle error } // receive message var buf [{buffSize}]byte _, err := conn.Read(buf[0:]) if err != nil { // handle error }
服务端代码:
// init tcpAddr, err := net.ResolveTCPAddr(resolver, serverAddr) if err != nil { // handle error } listener, err := net.ListenTCP("tcp", tcpAddr) if err != nil { // handle error } // listen for an incoming connection conn, err := listener.Accept() if err != nil { // handle error } // send message if _, err := conn.Write({message}); err != nil { // handle error } // receive message buf := make([]byte, 512) n, err := conn.Read(buf[0:]) if err != nil { // handle error }
与 TCP 套接字相比,使用 UDP 套接字时,客户端只需向服务器发送数据报。没有 Accept 函数,因为服务器不需要接受连接,只是等待数据报到达。
其他 TCP 函数有 UDP 对应函数;只需在上面的函数中将 TCP 替换为 UDP 即可。
客户端:
// init raddr, err := net.ResolveUDPAddr("udp", address) if err != nil { // handle error } conn, err := net.DialUDP("udp", nil, raddr) if err != nil { // handle error } ....... // send message buffer := make([]byte, maxBufferSize) n, addr, err := conn.ReadFrom(buffer) if err != nil { // handle error } ....... // receive message buffer := make([]byte, maxBufferSize) n, err = conn.WriteTo(buffer[:n], addr) if err != nil { // handle error }
服务端:
// init udpAddr, err := net.ResolveUDPAddr(resolver, serverAddr) if err != nil { // handle error } conn, err := net.ListenUDP("udp", udpAddr) if err != nil { // handle error } ....... // send message buffer := make([]byte, maxBufferSize) n, addr, err := conn.ReadFromUDP(buffer) if err != nil { // handle error } ....... // receive message buffer := make([]byte, maxBufferSize) n, err = conn.WriteToUDP(buffer[:n], addr) if err != nil { // handle error }
WebSocket 通信包通过单个 TCP 连接提供全双工通信通道。这意味着客户端和服务器都可以在需要时同时发送数据而无需任何请求。
对于需要持续数据交换的服务,例如即时通讯、在线游戏和实时交易系统,WebSockets 是一个很好的解决方案。您可以在 Internet 工程任务组 (IETF) ? ?RFC 6455 规范??中找到有关 WebSocket 协议的完整信息。
WebSocket 连接由浏览器请求并由服务器响应,然后建立连接。这个过程通常称为握手。 WebSockets 中的特殊类型的标头只需要浏览器和服务器之间的一次握手即可建立一个在其生命周期内保持活动状态的连接。
WebSocket 协议使用端口 80 进行不安全连接,使用端口 443 进行安全连接。 WebSocket 规范确定 ws (WebSocket) 和 wss (WebSocket Secure) 协议需要哪些统一的资源标识符方案。
这是客户端请求的样子:
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com
这是服务器响应:
HTTP/1.1 101 Switching Protocols Upgrade: websocketConnection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat
WebSockets 解决了开发实时 Web 应用程序的许多难题,并且与传统 HTTP 相比具有以下几个优点:
WebSocket
服务器可以将数据推送到 Web 客户端。WebSocket 协议实现起来比较简单。它使用 HTTP 协议进行初始握手。成功握手后,建立连接,WebSocket 本质上使用原始 TCP 读取/写入数据。