一、基于tcp的socket连接以及自定义消息头解析
package tcpsock
import (
"bufio"
"bytes"
"encoding/binary"
"fmt"
"log"
"main/api"
"net"
"unsafe"
)
type TASK_ON struct {
Msgid uint64 `json:"msgid"`
Num uint32 `json:"node_num"`
}
var Tasks = make(chan TASK_ON, 10)
type HEAD struct {
Data uint64 `json:"data"`
Length uint32 `json:"length"`
Magic uint16 `json:"magic"`
Sn [16]uint8 `json:"sn"`
Reserve uint32 `json:"reserve"`
}
func SocketConn() {
portList := []string{"8888", "9090"}
for _, port := range portList {
go func(p string) {
listener, err := net.Listen("tcp", ":"+p)
if err != nil {
fmt.Println("Error listening on port", p, ":", err)
return
}
defer listener.Close()
fmt.Println("Listening on port", p)
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting connection on port", p, ":", err)
continue
}
go handleConnection(conn)
}
}(port)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
fmt.Println("Accepted connection from", conn.RemoteAddr())
go func() {
for v := range Tasks {
fmt.Println("Received ", v)
}
}()
// 针对当前连接做发送和接收操作
for {
reader := bufio.NewReader(conn)
buf := make([]byte, 4096)
n, err := reader.Read(buf[:])
if n <= 0 && err != nil {
fmt.Printf("read from conn failed, err:%v\n", err)
break
}
//基于bytes+bianry反序列化
var dataS HEAD
var byteB []byte = buf
err2 := binary.Read(bytes.NewReader(byteB), binary.LittleEndian, &dataS)
if err2 != nil {
log.Panic(err2)
}
fmt.Printf("反序列化后:%x,%d,%s\n", dataS.Magic, dataS.Length, dataS.Sn)
//基于encoding/binary反序列化(已知字节长度)
fmt.Printf("data:%d\n", binary.LittleEndian.Uint64(buf[:8]))
fmt.Printf("length:%d\n", binary.LittleEndian.Uint32(buf[8:12]))
fmt.Printf("magic:%x\n", binary.LittleEndian.Uint16(buf[12:14]))
fmt.Printf("sn:%s\n", string(buf[14:30]))
fmt.Printf("n=%d,收到的数据:%d\n", n, buf[:n])
//基于unsafe反序列化
unsafe_s := UnmashalUnsafe(buf)
if unsafe_s.Magic == 0xEEFE {
fmt.Println("ptestStruct is : ", unsafe_s)
}
// 将接受到的数据返回给客户端
n, err = conn.Write(byteB[:n])
if err != nil {
fmt.Printf("write from conn failed, err:%v\n", err)
break
}
fmt.Println("已发送数据长度:", n)
}
}
func UnmashalUnsafe(buf []byte) *HEAD {
//基于unsafe反序列化
var ptestStruct *HEAD = *(**HEAD)(unsafe.Pointer(&buf))
return ptestStruct
}
二、websocket的简单使用
package upgrader
import (
"encoding/json"
"fmt"
"log"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
type TASK_ON struct {
Msgid uint64 `json:"msgid"`
Num uint32 `json:"node_num"`
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
// 取消ws跨域校验
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func WsHandler(c *gin.Context) {
client, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
client.SetCloseHandler(func(code int, text string) error {
return nil
})
for {
typ, message, err := client.ReadMessage()
if err != nil {
log.Println(err)
break
}
log.Printf("Received:%s,%d", message, typ)
task := TASK_ON{}
err = json.Unmarshal([]byte(message), &task)
if err != nil {
fmt.Println("ERROR:", err.Error())
return
}
log.Println("Received:", task)
// ws连接建立收到消息给前端推送消息
err = client.WriteMessage(websocket.TextMessage, []byte("client received"))
if err != nil {
log.Println(err)
}
}
}