跳到主要内容

websocket开发测试

about websocket长连接

WebSocket是应用层第七层上的一个网络传输协议,它必须依赖HTTP协议进行一次握手,握手成功后数据就直接从TCP通道传输。即WebSocket分为握手和数据传输阶段,简单而言即http握手+双工的TCP连接。

简单点理解,WebSocket是一种在单个TCP连接上进行全双工通信的协议,长连接,双向传输

特点:

  • 通信高效
  • 没有同源限制,客户端可以与任意服务端通信
  • 协议标识符是ws(如果加密,则为wss),ws和http的默认端口都是80,wss和https的默认端口都是443

websocket由http升级而来,首先发送附带Upgrade请求头的Http请求,所以我们需要在处理Http请求时拦截请求并判断其是否为websocket升级请求.

WebSocket 协议实现起来相对简单。 HTTP 协议初始握手建立连接,WebSocket 实质上使用原始 TCP 读取 / 写入数据.

服务端

接收与发送。多用户并发。

测试代码

sr.go
package main

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

// 定义一个对像upgrade_test
var upgrade_test = websocket.Upgrader{
ReadBufferSize: 1124,
WriteBufferSize: 1124,
CheckOrigin: func(r *http.Request) bool {
return true
},
}

func handler_url(w http.ResponseWriter, r *http.Request) {
//1.升级协议,并返回升级后的长连接
conn, err := upgrade_test.Upgrade(w, r, nil)
if err != nil {
log.Println("Error during connection upgrade:", err)
return
}
defer conn.Close()

//读取客户端的请求信息,返回
for {
// 2.读取客户端的请求信息
messageType, message, err := conn.ReadMessage()
if err != nil {
log.Println("Error during message writing:", err)
return
}
log.Printf("从客户端接收信息(Recive message):%s,From:%s", message, conn.RemoteAddr().String()) //将信息显示在服务端屏幕上。

// 3.返回给客户端信息
err = conn.WriteMessage(messageType, message)
if err != nil {
log.Println("Error during message writing:", err)
return
}
}
}

func main() {
http.HandleFunc("/test", handler_url)
err := http.ListenAndServe(":8080", nil) //启动http服务器
if err != nil {
log.Fatalln(err)
}
}

编译测试

# go build
# ./sr
# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=777,fd=3))
LISTEN 0 511 *:8080 *:* users:(("sr",pid=2974,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=777,fd=4))

客户端

发送与接收

测试源码

client.go
package main

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

func ReceiveHandler(con *websocket.Conn) {
for {
_, message, err := con.ReadMessage()
if err != nil {
log.Println("Error during Receive:", err)
return
}
log.Printf("从服务端接收到的信息(Receive):%s,From:%s\n", message, con.RemoteAddr().String())
}
}

func main() {
socketUrl := "ws://127.0.0.1:8080" + "/test"
// 使用 net.Dialer Dialer.Dial 函数建立 TCP 连接,建立成功后,取得了 net.Conn 对象,
conn, _, err := websocket.DefaultDialer.Dial(socketUrl, nil)
if err != nil {
log.Fatal("Error connecting to websocket Server:", err)
}
defer conn.Close()

//使用定时器向服务端发信息,每1秒发一次数据。
ticker := time.Tick(time.Second)
for range ticker {
err = conn.WriteMessage(websocket.TextMessage, []byte("Hello World!"))
if err != nil {
log.Println("Error during writing to websocket:", err)
return
}
// 接受客户端消息使用ReadMessage()该操作会阻塞线程所以建议运行在其他协程上
go ReceiveHandler(conn)
}
}

编译测试

# go build
# ./client
2023/10/09 13:31:02 从服务端接收到的信息(Receive):Hello World!,From:127.0.0.1:8080
2023/10/09 13:31:03 从服务端接收到的信息(Receive):Hello World!,From:127.0.0.1:8080
2023/10/09 13:31:04 从服务端接收到的信息(Receive):Hello World!,From:127.0.0.1:8080
2023/10/09 13:31:05 从服务端接收到的信息(Receive):Hello World!,From:127.0.0.1:8080
2023/10/09 13:31:06 从服务端接收到的信息(Receive):Hello World!,From:127.0.0.1:8080
2023/10/09 13:31:07 从服务端接收到的信息(Receive):Hello World!,From:127.0.0.1:8080
2023/10/09 13:31:08 从服务端接收到的信息(Receive):Hello World!,From:127.0.0.1:8080
2023/10/09 13:31:09 从服务端接收到的信息(Receive):Hello World!,From:127.0.0.1:8080

此时在sr端可以看到

# ./sr
2023/10/09 13:31:02 从客户端接收信息(Recive message):Hello World!,From:127.0.0.1:49562
2023/10/09 13:31:03 从客户端接收信息(Recive message):Hello World!,From:127.0.0.1:49562
2023/10/09 13:31:04 从客户端接收信息(Recive message):Hello World!,From:127.0.0.1:49562
2023/10/09 13:31:05 从客户端接收信息(Recive message):Hello World!,From:127.0.0.1:49562
2023/10/09 13:31:06 从客户端接收信息(Recive message):Hello World!,From:127.0.0.1:49562
2023/10/09 13:31:07 从客户端接收信息(Recive message):Hello World!,From:127.0.0.1:49562
2023/10/09 13:31:08 从客户端接收信息(Recive message):Hello World!,From:127.0.0.1:49562
2023/10/09 13:31:09 从客户端接收信息(Recive message):Hello World!,From:127.0.0.1:49562