Go 实现 WebSockets和什么是 WebSockets
作者:宇宙之一粟 时间:2024-04-26 17:15:42
前言
日常工作中,在不刷新页面的情况下发送消息并获得即时响应是我们认为理所当然的事情。但在过去,启用实时功能对开发人员来说是一个真正的挑战。开发者社区从 HTTP 长轮询和 AJAX 走过了漫长的道路,终于找到了构建真正实时应用程序的解决方案。
这个解决方案以 WebSockets 的形式出现,它可以在用户的浏览器和服务器之间打开一个交互式会话。 WebSockets 允许浏览器向服务器发送消息并接收事件驱动的响应,而无需轮询服务器以获取回复。
目前,WebSockets
是构建实时应用程序的第一大解决方案:在线游戏、即时通讯、跟踪应用程序等。
本文将解释 WebSockets
的运作方式,然后使用 Go 语言构建一个简单的 WebSocket 应用程序。
什么是 WebSockets
简而言之,WebSocket是一种 Web 技术,可以通过持久的单个套接字连接实现客户端和服务器之间的双向,全双工通信。WebSocket 是为 Web 应用程序开发人员提供基本上是一个接近原始的TCP通信层。
WebSocket 连接以 HTTP 请求/响应握手启动。如果此初始握手成功,则客户端和服务器已同意使用为 HTTP 请求作为 WebSocket 连接建立的现有 TCP / IP 连接。只要需要一旦 WebSocket 连接服务了它的目的,它可以通过关闭握手终止,客户端和服务器都可以启动。
WebSockets 标志着 Web 开发的转折点。直到 WebSockets 的出现,实时网络难以实现和慢于我们习惯于现在;它是通过使用像 Ajax 和 Comet (长)轮询的技术提供的技术,这些轮询没有真正优化用于实时应用。
WebSocket 技术具有广泛的适用性。您可以在不同的目的中使用它,例如后端服务之间的流数据,或者通过长期的全双工连接连接前端。简而言之,WebSockets 是架构事件驱动的系统和构建实时应用程序和服务的绝佳选择,在那里它必须随时随地提供数据所必需的数据。
我们可以将 WebSocket 用例大致分为两个不同的类别:
实时更新。通信是单向的,服务器将低延迟(通常是频繁的)更新流式传输到客户端。想想现场体育更新、警报、实时仪表板或位置跟踪,仅举几个用例
双向通信。客户端和服务器都发送和接收消息。示例包括聊天,虚拟事件和虚拟教室(最后两个通常涉及轮询,测验和 Q&AS )等功能。WebSocket 还可用于支撑多用户同步协作功能,例如同时编辑同一文档的多个人员
网络套接字与 WebSockets
网络套接字,或简称为套接字,用作在同一台计算机或同一网络上不同计算机上运行的应用程序之间交换数据的内部端点。
套接字是基于 Unix 和 Windows 的操作系统的关键部分,它们使开发人员更容易创建支持网络的软件。应用程序开发人员可以在他们的程序中包含套接字,而不是从头开始构建网络连接。由于网络套接字用于多种网络协议(HTTP、FTP 等),因此可以同时使用多个套接字。
套接字是由套接字的应用程序编程接口 (API) 定义的一组函数调用创建和使用的。
有几种类型的网络套接字:
数据报套接字(SOCK_DGRAM),也称为无连接套接字,使用用户数据报协议 (UDP)。数据报套接字支持双向消息流并保留记录边界。
流式套接字(SOCK_STREAM),也称为面向连接的套接字,使用传输控制协议 (TCP)、流控制传输协议 (SCTP) 或数据报拥塞控制协议 (DCCP)。这些套接字提供双向、可靠、有序且不重复的数据流,没有记录边界。
原始套接字(raw IP sockets) 通常在路由器和其他网络设备中可用。这些套接字通常是面向数据报的,尽管它们的确切特性取决于协议提供的接口。大多数应用程序不使用原始套接字。提供它们是为了支持新通信协议的开发,并提供对现有协议更深奥的设施的访问。
套接字通信
每个网络套接字由地址标识,地址是传输协议、IP 地址和端口号的三元组。
主机之间的通信主要有两种协议:TCP 和 UDP。让我们看看您的应用程序如何连接到 TCP 和 UDP 套接字。
连接到 TCP 套接字
为了建立 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
}
连接到 UDP 套接字
与 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
}
来源:https://blog.51cto.com/yuzhou1su/5184571


猜你喜欢
Python爬虫爬取美剧网站的实现代码

Python基于opencv的图像压缩算法实例分析
Python 3.6 中使用pdfminer解析pdf文件的实现

MySQL无法存储emoji表情解决方案分析
python 利用jinja2模板生成html代码实例
THREE.JS入门教程(5)你应当知道的十件事
深入PHP magic quotes的详解

带农历的JavaScript日期时间js代码
python 画3维轨迹图并进行比较的实例

Django启动时找不到mysqlclient问题解决方案

Python正则表达式re.sub()用法详解

简单了解python 生成器 列表推导式 生成器表达式
JS通过FSO将unicode字符写入文本
Git科普文,Git基本原理及各种骚操作(推荐)

python实现多线程暴力破解登陆路由器功能代码分享
对python中list的拷贝与numpy的array的拷贝详解

asp如何做一个只能从本站点才能访问的页面?
Tensorflow 训练自己的数据集将数据直接导入到内存

简单PHP上传图片、删除图片实现代码
Go语言开发kube-scheduler整体架构深度剖析
