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

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)
    }
}
时间: 2024-11-07 16:54:52

golang 自定义封包协议(转的)的相关文章

golang自定义数据类型查询与插入postgresql中point数据

golang自定义数据类型查询与插入postgresql中point数据 具体代码如下: package main import ( "bytes" "database/sql" "database/sql/driver" "fmt" _ "github.com/lib/pq" "strconv" "strings" ) // 自定义支持类型 type Point s

[转]Windows 注册自定义的协议

[转自] http://blog.sina.com.cn/s/blog_86e4a51c01010nik.html 1.注册应用程序来处理自定义协议 你必须添加一个新的key以及相关的value到HKEY_CLASSES_ROOT中,来使应用程序可以处理特殊的URL协议. 新注册的key必须与协议scheme相匹配才可以被添加.例如,增加一个“alert:”协议,被增加到HKEY_CLASSES_ROOT的key必须是alert.在这个新的key之下,默认的字符串value将显示新协议的名字,并

呕心沥血的java复杂项目(包括自定义应用层协议、CS多线程、多客户端登录、上下线提醒等等)

建议大家先下源代码,导入到Eclipse,然后运行服务器和多个客户端,这样有个不错的体会.下载地址:http://download.csdn.net/detail/woshiwanghao_hi/7320927. 首先来看下整个系统的文件架构图: 系统是个基于UDP的聊天室,因为不能保持所有用户和聊天室的持续连接.同时为了保持数据传输的可靠性,就需要自定义应用层协议了. 程序大概的一个流程如下: 1.启动服务器,点击"start service",之后服务器及开始监听指定端口. 2.启

(转)通过自定义URL协议在Web中启动本地应用程序

通过自定义URL协议在Web中启动本地应用程序 1.注册应用程序来处理自定义协议 你必须添加一个新的key以及相关的value到HKEY_CLASSES_ROOT中,来使应用程序可以处理特殊的URL协议. 新注册的key必须与协议scheme相匹配才可以被添加.例如,增加一个“alert:”协议,被增加到HKEY_CLASSES_ROOT的key必须是alert.在这个新的key之下,默认的字符串value将显示新协议的名字,并且URL协议字符串value将包含协议特有的信息或者空字符串.Key

golang 自定义importpath

golang 的包导入和其他语言有好多不一样的地方,以下是一个自定义的导入 golang 自定义导入说明 一个官方的说明 比较简单,就不翻译了,主要是说我们可以通过添加meta 数据告诉包如何进行加载 For example, import "example.org/pkg/foo" will result in the following requests: https://example.org/pkg/foo?go-get=1 (preferred) http://example

netty5自定义私有协议实例

自定义协议可以解决粘包和拆包问题,客户端发送数据时携带数据包长度,服务端接收数据后解析消息体,获取数据包长度值,据此继续获取数据包内容.我们来看具体例子,自定义的协议如下: +--------------------------------------------------+----------+  |                消息头                | 消息体 |  | Delimiter | Length | Type | Reserved  |   data   | 

[Golang] 从零开始写Socket Server(2): 自定义通讯协议

在上一章我们做出来一个最基础的demo后,已经可以初步实现Server和Client之间的信息交流了~ 这一章我会介绍一下怎么在Server和Client之间实现一个简单的通讯协议,从而增强整个信息交流过程的稳定性. 在Server和client的交互过程中,有时候很难避免出现网络波动,而在通讯质量较差的时候,Client有可能无法将信息流一次性完整发送,最终传到Server上的信息很可能变为很多段. 如下图所示,本来应该是分条传输的json,结果因为一些原因连接在了一起,这时候就会出现问题啦,

自定义socket协议(服务端)

自定义协议服务 // server.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <stdio.h> #include <winsock2.h> #pragma comment(lib,"Ws2_32") #define SERVER_PORT 2000 

IP封包协议头/TCP协议头/TCP3次握手/TCP4次挥手/UDP协议头/ICMP协议头/HTTP协议(请求报文和响应报文)/IP地址/子网掩码(划分子网)/路由概念/MAC封包格式

IP协议头IP包头格式: 1.版本号:4个bit,用来标识IP版本号.这个4位字段的值设置为二进制的0100表示IPv4,设置为0110表示IPv6.目前使用的IP协议版本号是4. 2.首部长度:4个bit.标识包括选项在内的IP头部字段的长度. 3.服务类型:8个bit.服务类型字段被划分成两个子字段:3bit的优先级字段和4bit TOS字段,最后一位置为0. 4bit的TOS分别代表:最小时延,最大吞吐量,最高可靠性和最小花费.4bit中只能将其中一个bit位置1.如果4个bit均为0,则