golang 自定义封包协议(转的)

简介: package protocol import ( "bytes" "encoding/binary" ) const ( ConstHeader = "jackluo" ConstHeaderLength = 7 ...
package protocol
 
import (
    "bytes"
    "encoding/binary"
)
 
const (
    ConstHeader         = "jackluo"
    ConstHeaderLength   = 7
    ConstSaveDataLength = 4
)
 
//封包
func Packet(message []byte) []byte {
    return append(append([]byte(ConstHeader), IntToBytes(len(message))...), message...)
}
 
//解包
func Unpack(buffer []byte, readerChannel chan []byte) []byte {
    length := len(buffer)
 
    var i int
    for i = 0; i < length; i = i + 1 {
        if length < i+ConstHeaderLength+ConstSaveDataLength {
            break
        }
        if string(buffer[i:i+ConstHeaderLength]) == ConstHeader {
            messageLength := BytesToInt(buffer[i+ConstHeaderLength : i+ConstHeaderLength+ConstSaveDataLength])
            if length < i+ConstHeaderLength+ConstSaveDataLength+messageLength {
                break
            }
            data := buffer[i+ConstHeaderLength+ConstSaveDataLength : i+ConstHeaderLength+ConstSaveDataLength+messageLength]
            readerChannel <- data
 
            i += ConstHeaderLength + ConstSaveDataLength + messageLength - 1
        }
    }
 
    if i == length {
        return make([]byte, 0)
    }
    return buffer[i:]
}
 
//整形转换成字节
func IntToBytes(n int) []byte {
    x := int32(n)
 
    bytesBuffer := bytes.NewBuffer([]byte{})
    binary.Write(bytesBuffer, binary.BigEndian, x)
    return bytesBuffer.Bytes()
}
 
//字节转换成整形
func BytesToInt(b []byte) int {
    bytesBuffer := bytes.NewBuffer(b)
 
    var x int32
    binary.Read(bytesBuffer, binary.BigEndian, &x)
 
    return int(x)
}
package main

import (
    "fmt"
    "net"
    "os"
    "./protocol"
)

func main() {
    netListen, err := net.Listen("tcp", ":9988")
    CheckError(err)
 
    defer netListen.Close()
 
    Log("Waiting for clients")
    for {
        conn, err := netListen.Accept()
        if err != nil {
            continue
        }
 
        Log(conn.RemoteAddr().String(), " tcp connect success")
        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
   
    //声明一个临时缓冲区,用来存储被截断的数据
    tmpBuffer := make([]byte, 0) 
    //声明一个管道用于接收解包的数据
    readerChannel := make(chan []byte, 16)
    go reader(readerChannel)

    buffer := make([]byte, 1024)
    for {
        n, err := conn.Read(buffer)
        if err != nil {
            Log(conn.RemoteAddr().String(), " connection error: ", err)
            return
        }
/*        Log(conn.RemoteAddr().String(), "receive data length:", n)
        Log(conn.RemoteAddr().String(), "receive data:", buffer[:n])
        Log(conn.RemoteAddr().String(), "receive data string:", string(buffer[:n]))
*/  
     tmpBuffer = protocol.Unpack(append(tmpBuffer, buffer[:n]...), readerChannel)  
    }
}
func reader(readerChannel chan []byte) {
    for {
        select {
        case data := <-readerChannel:
            Log(string(data))
        }
    }
}
func Log(v ...interface{}) {
    fmt.Println(v...)
}
 
func CheckError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        os.Exit(1)
    }
}
package main
 
import (
    "fmt"
    "net"
    "os"
    "time"
    "./protocol"
)
 
func sender(conn net.Conn) {
    for i := 0; i < 100; i++ {
        words := "{\"Id\":1,\"Name\":\"golang\",\"Message\":\"message\"}"
        conn.Write(protocol.Packet([]byte(words)))
    }
     fmt.Println("send over")
}
 
func main() {
    server := "127.0.0.1:9988"
    tcpAddr, err := net.ResolveTCPAddr("tcp4", server)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        os.Exit(1)
    }
 
    conn, err := net.DialTCP("tcp", nil, tcpAddr)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        os.Exit(1)
    }
 
    defer conn.Close()
 
    fmt.Println("connect success")
 
    go sender(conn)
 
    for {
        time.Sleep(1 * 1e9)
    }
}

 

目录
相关文章
|
5月前
|
Go 区块链
go 编译 自定义 图标 ico文件
go 编译 自定义 图标 ico文件
41 0
|
5月前
|
关系型数据库 Go PostgreSQL
golang pgx自定义PostgreSQL类型
golang的pgx驱动提供了大约70种PostgreSQL类型支持,但还是有一些类型没有涵盖,本文介绍如何自己编写代码支持特殊的类型。
80 3
|
5月前
|
监控 网络协议 Go
Golang抓包:实现网络数据包捕获与分析
Golang抓包:实现网络数据包捕获与分析
|
6月前
|
负载均衡 中间件 Go
Golang 微服务工具包 Go kit
Golang 微服务工具包 Go kit
43 0
|
6月前
|
存储 Go
Golang 语言标准库 sync/atomic 包原子操作
Golang 语言标准库 sync/atomic 包原子操作
25 0
|
6月前
|
Unix Go
Golang 语言的标准库 os 包怎么操作目录和文件?
Golang 语言的标准库 os 包怎么操作目录和文件?
28 0
|
3月前
|
物联网 Go 网络性能优化
使用Go语言(Golang)可以实现MQTT协议的点对点(P2P)消息发送。MQTT协议本身支持多种消息收发模式
使用Go语言(Golang)可以实现MQTT协议的点对点(P2P)消息发送。MQTT协议本身支持多种消息收发模式【1月更文挑战第21天】【1月更文挑战第104篇】
102 1
|
3月前
|
NoSQL Go Redis
Golang实现redis系列-(3)封装RESP协议
Golang实现redis系列-(3)封装RESP协议
36 0
|
1天前
|
Go 开发者
Golang深入浅出之-HTTP客户端编程:使用net/http包发起请求
【4月更文挑战第24天】Go语言的`net/http`包在HTTP客户端编程中扮演重要角色,但使用时需注意几个常见问题:1) 检查HTTP状态码以确保请求成功;2) 记得关闭响应体以防止资源泄漏;3) 设置超时限制,避免长时间等待;4) 根据需求处理重定向。理解这些细节能提升HTTP客户端编程的效率和质量。
11 1
|
1天前
|
Go 开发者
Golang深入浅出之-Go语言上下文(context)包:处理取消与超时
【4月更文挑战第23天】Go语言的`context`包提供`Context`接口用于处理任务取消、超时和截止日期。通过传递`Context`对象,开发者能轻松实现复杂控制流。本文解析`context`包特性,讨论常见问题和解决方案,并给出代码示例。关键点包括:1) 确保将`Context`传递给所有相关任务;2) 根据需求选择适当的`Context`创建函数;3) 定期检查`Done()`通道以响应取消请求。正确使用`context`包能提升Go程序的控制流管理效率。
7 1