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)
}
}

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

  1. Newtonsoft.Json 自定义 解析协议

    在开发web api的时候 遇到一个要把string未赋值默认为null的情况改成默认为空字符串的需求 这种情况就需要自定义json序列话的 解析协议了 Newtonsoft.Json默认的解析协议是 ...

  2. 【Win 10开发】协议-上篇:自定义应用协议

    就像系统许多内置应用可以通过URI来启动(如ms-settings-bluetooth:可以打开蓝牙设置页),我们自己开发的应用程序,如果需要的话,可以为应用程序自定义一个协议.应用程序协议在安装时会 ...

  3. TeamTalk自定义IM协议的理解

    一.TeamTalk自定义IM协议 TeamTalk自定义IM协议是一种基于protocol buffer的消息传递协议,protocol buffer可以自定义消息格式.protocol buffe ...

  4. golang 自定义importpath

    golang 的包导入和其他语言有好多不一样的地方,以下是一个自定义的导入 golang 自定义导入说明 一个官方的说明 比较简单,就不翻译了,主要是说我们可以通过添加meta 数据告诉包如何进行加载 ...

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

    [转自] http://blog.sina.com.cn/s/blog_86e4a51c01010nik.html 1.注册应用程序来处理自定义协议 你必须添加一个新的key以及相关的value到HK ...

  6. 自定义URL协议在Web中启动本地应用程序

    转自(http://blog.csdn.net/jackychen_king/article/details/7743811) 1.注册应用程序来处理自定义协议 你必须添加一个新的key以及相关的va ...

  7. mac下自定义伪协议配置

    之前查了很多资料,最近也在挖掘研究这方面的漏洞. windows的很简单,在注册表配置就好了,但是mac os 是unix的,没有注册表这么一说. 但是发现腾讯等配置了自定义等协议,例如:tencen ...

  8. netty5自定义私有协议实例

    一般业务需求都会自行定义私有协议来满足自己的业务场景,私有协议也可以解决粘包和拆包问题,比如客户端发送数据时携带数据包长度,服务端接收数据后解析消息体,获取数据包长度值,据此继续获取数据包内容.我们来 ...

  9. 基于Netty的RPC架构学习笔记(九):自定义序列化协议

    文章目录 为什么需要自定义序列化协议

随机推荐

  1. 恢复 git reset -hard 的误操作

    有时候使用Git工作得小心翼翼,特别是涉及到一些高级操作,例如 reset, rebase 和 merge.甚至一些很小的操作,例如删除一个分支,我都担心数据丢失. 不 久之前,我在做一些大动作(re ...

  2. Linux下修改默认字符集--->解决Linux下Java程序种中文文件夹file.isDirectory()判断失败的问题

    一.问题描述: 一个项目中为了生成树状目录,调用了file.listFiles()方法,然后利用file.isDirectory()方法判断是否为目录,该程序在windows下运行无问题,在Linux ...

  3. JavaScript - 基本概念

    相等操作符 == 和 != 是先转换再比较 === 和 !== 是直接比较,不经过转换 中文翻译上来说叫做相等和全等.类型转换简单的概括就是高级转低级,比如说布尔字符串转数字,对象取值再转.相等比较有 ...

  4. linux SecureCRT ssh key认证登陆

    转自:http://blog.chinaunix.net/uid-20639775-id-3207171.html 通过SecureCRT创建key登录认证 一.生成公钥/密钥对 使用SecureCR ...

  5. Spring之ResourceLoader加载资源

    Resource与ResourceLoader对比 1.Resource接口定义了应用访问底层资源的能力. 通过FileSystemResource以文件系统绝对路径的方式进行访问: 通过ClassP ...

  6. Jquery获取select,dropdownlist,checkbox下拉列表框的值

       jQuery获取 Select选择的Text和Value: 语法解释: 1. $("#select_id").change(function(){//code...});   ...

  7. 简单记录在Visual Studio 2013中创建ASP.NET Web API 2

    在很多跨平台的应用中就需要Web API ,比如android与数据库的交互. Create a Web API Project 选择新建项目下的模板下的Visual C#节点下的Web节点,在模板列 ...

  8. 在CentOS中快速安装PHP,MySQL,Nginx和phpMyAdmin

    安装环境 yum install -y autoconf automake gcc gcc-c++ git libtool make nasm pkgconfig zlib-devel vim 安装p ...

  9. 《DSP using MATLAB》示例Example4.10

    上代码: b = [1, 0.4*sqrt(2)]; a = [1, -0.8*sqrt(2), 0.64]; % compute the polynomials coefficients given ...

  10. java.net.SocketException: No buffer space available

    https 访问url在调用量不大的情况下 java.net.SocketException: No buffer space available (maximum connections reach ...