WebSocket协议、与HTTP对比

发布时间:2024年01月19日

WebSocket

也可前往本人的个人网站进行阅读

WebSocket 和 HTTP

WebSocket和HTTP协议一样,都是基于TCP协议实现的应用层协议。

HTTP协议通常是单边通信,主要用于传输静态文档、请求-响应通信,适用于Web浏览器加载网页、API调用等。然而WebSocket则是会主动给你发消息,实现实时双向通信,我们经常玩的游戏、使用的聊天软件什么采用的都是这个协议。

这里进行详细比较

共同点:

  1. 基于TCP: WebSocket和HTTP都是基于TCP协议的应用层协议,用于在客户端和服务器之间进行通信。
  2. 使用URI(统一资源标识符): 两者都使用统一资源标识符(URI)来标识资源或服务的位置。
  3. 都是面向应用层的协议: WebSocket和HTTP都属于应用层协议,用于在不同设备或应用程序之间进行通信。

不同点:

  1. 连接性和通信方式:
    • HTTP: 是一种无状态的请求-响应协议。每个HTTP请求都是独立的,服务器在每个请求之后会断开连接,需要在每次请求时重新建立连接。
    • WebSocket: 提供了全双工通信,允许客户端和服务器之间建立持久的连接,可以实现双向实时通信,而不需要为每个消息建立新的连接。
  2. 数据帧格式:
    • HTTP: 通常使用明文文本或基于二进制的数据传输,但每个请求和响应都具有特定的结构。
    • WebSocket: 使用帧(frame)的形式传输数据,可以是文本帧或二进制帧。
  3. 协议头和握手:
    • HTTP: 通过请求头和响应头来传递元数据信息,如请求方法、状态码等。
    • WebSocket: 在建立连接时,使用HTTP进行初始握手,然后切换到WebSocket协议。握手时使用特定的HTTP头部,如Upgrade和Connection。
  4. 目的和应用场景:
    • HTTP: 主要用于传输静态文档、请求-响应通信,适用于Web浏览器加载网页、API调用等。
    • WebSocket: 适用于需要实时、双向通信的应用场景,如实时聊天、在线游戏、股票市场数据更新等。

总的来说,WebSocket和HTTP都是网络通信中的重要协议,但它们在连接性、通信方式和应用场景等方面存在明显的区别。WebSocket更适合实时、双向通信,而HTTP主要用于请求-响应式的通信。

解析

接下来对此协议进行详细讲解,先看图:

https://asdxz.oss-cn-beijing.aliyuncs.com/pic/20240115181050.png

首先客户端(client)发送连接请求,通过HTTP发送到服务端,但是请求头会进行一定改变,比如:

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

这其中包含了一些特殊的头部,比如 UpgradeConnection

服务器接收到这个请求后,如果支持WebSocket,就会回复一个HTTP 101状态码(切换协议)以及一些额外的头部,表示同意建立WebSocket连接

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

此过程则称为握手,服务端和客户端握手建立连接之后,连接将一直保持,直到其中一方终止

过程中的数据传输:客户端和服务器可以在连接上自由地发送文本或二进制数据帧。这些数据帧包含消息内容以及一些控制信息,如数据帧的类型和长度等

关闭连接:关闭连接时,终止方会发送一个特殊的关闭帧。

例子

以下是一个golang的例子

package main

import (
	"log"
	"net/http"
	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func handleConnections(w http.ResponseWriter, r *http.Request) {
	// 将HTTP连接升级为WebSocket连接
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Fatal(err)
		return
	}
	defer conn.Close()

	for {
		// 读取客户端发送的消息
		messageType, p, err := conn.ReadMessage()
		if err != nil {
			log.Println(err)
			return
		}

		// 将接收到的消息原样发送回客户端
		if err := conn.WriteMessage(messageType, p); err != nil {
			log.Println(err)
			return
		}
	}
}

func main() {
	http.HandleFunc("/ws", handleConnections)
	log.Println("WebSocket server is running on :8080")
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		log.Fatal("Error starting server: ", err)
	}
}

客户端

package main

import (
	"fmt"
	"log"
	"github.com/gorilla/websocket"
)

func main() {
	// 连接WebSocket服务器
	conn, _, err := websocket.DefaultDialer.Dial("ws://localhost:8080/ws", nil)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// 向服务器发送消息
	message := []byte("Hello, WebSocket!")
	err = conn.WriteMessage(websocket.TextMessage, message)
	if err != nil {
		log.Fatal(err)
	}

	// 从服务器接收消息
	_, receivedMessage, err := conn.ReadMessage()
	if err != nil {
		log.Fatal(err)
	}

	// 打印接收到的消息
	fmt.Println("Received message from server:", string(receivedMessage))
}

最后效果:

https://asdxz.oss-cn-beijing.aliyuncs.com/pic/20240115224711.png

文章来源:https://blog.csdn.net/m0_73976305/article/details/135704489
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。