aceld
6 years ago
11 changed files with 386 additions and 54 deletions
-
47utils/globalobj.go
-
6ziface/iconnection.go
-
11ziface/idatapack.go
-
14ziface/imessage.go
-
1ziface/irequest.go
-
70znet/connection.go
-
71znet/datapack.go
-
107znet/datepack_test.go
-
46znet/message.go
-
9znet/request.go
-
58znet/server_test.go
@ -0,0 +1,11 @@ |
|||
package ziface |
|||
|
|||
/* |
|||
封包数据和拆包数据 |
|||
直接面向TCP连接中的数据流,为传输数据添加头部信息,用于处理TCP粘包问题。 |
|||
*/ |
|||
type IDataPack interface{ |
|||
GetHeadLen() uint32 //获取包头长度方法
|
|||
Pack(msg IMessage)([]byte, error) //封包方法
|
|||
Unpack([]byte)(IMessage, error) //拆包方法
|
|||
} |
@ -0,0 +1,14 @@ |
|||
package ziface |
|||
|
|||
/* |
|||
将请求的一个消息封装到message中,定义抽象层接口 |
|||
*/ |
|||
type IMessage interface { |
|||
GetDataLen() uint32 //获取消息数据段长度
|
|||
GetMsgId() uint32 //获取消息ID
|
|||
GetData() []byte //获取消息内容
|
|||
|
|||
SetMsgId(uint32) //设计消息ID
|
|||
SetData([]byte) //设计消息内容
|
|||
SetDataLen(uint32) //设置消息数据段长度
|
|||
} |
@ -0,0 +1,71 @@ |
|||
package znet |
|||
|
|||
import ( |
|||
"bytes" |
|||
"encoding/binary" |
|||
"errors" |
|||
"zinx/utils" |
|||
"zinx/ziface" |
|||
) |
|||
|
|||
//封包拆包类实例,暂时不需要成员
|
|||
type DataPack struct {} |
|||
|
|||
//封包拆包实例初始化方法
|
|||
func NewDataPack() *DataPack { |
|||
return &DataPack{} |
|||
} |
|||
|
|||
//获取包头长度方法
|
|||
func(dp *DataPack) GetHeadLen() uint32 { |
|||
//Id uint32(4字节) + DataLen uint32(4字节)
|
|||
return 8 |
|||
} |
|||
//封包方法(压缩数据)
|
|||
func(dp *DataPack) Pack(msg ziface.IMessage)([]byte, error) { |
|||
//创建一个存放bytes字节的缓冲
|
|||
dataBuff := bytes.NewBuffer([]byte{}) |
|||
|
|||
//写msgID
|
|||
if err := binary.Write(dataBuff, binary.LittleEndian, msg.GetMsgId()); err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
//写dataLen
|
|||
if err := binary.Write(dataBuff, binary.LittleEndian, msg.GetDataLen()); err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
//写data数据
|
|||
if err := binary.Write(dataBuff, binary.LittleEndian, msg.GetData()); err != nil { |
|||
return nil ,err |
|||
} |
|||
|
|||
return dataBuff.Bytes(), nil |
|||
} |
|||
//拆包方法(解压数据)
|
|||
func(dp *DataPack) Unpack(binaryData []byte)(ziface.IMessage, error) { |
|||
//创建一个从输入二进制数据的ioReader
|
|||
dataBuff := bytes.NewReader(binaryData) |
|||
|
|||
//只解压head的信息,得到dataLen和msgID
|
|||
msg := &Message{} |
|||
|
|||
//读msgID
|
|||
if err := binary.Read(dataBuff, binary.LittleEndian, &msg.Id); err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
//读dataLen
|
|||
if err := binary.Read(dataBuff, binary.LittleEndian, &msg.DataLen); err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
//判断dataLen的长度是否超出我们允许的最大包长度
|
|||
if (utils.GlobalObject.MaxPacketSize > 0 && msg.DataLen > utils.GlobalObject.MaxPacketSize) { |
|||
return nil, errors.New("Too large msg data recieved") |
|||
} |
|||
|
|||
//这里只需要把head的数据拆包出来就可以了,然后再通过head的长度,再从conn读取一次数据
|
|||
return msg, nil |
|||
} |
@ -0,0 +1,107 @@ |
|||
package znet |
|||
|
|||
import ( |
|||
"fmt" |
|||
"io" |
|||
"net" |
|||
"testing" |
|||
) |
|||
|
|||
//只是负责测试datapack拆包,封包功能
|
|||
func TestDataPack(t *testing.T) { |
|||
//创建socket TCP Server
|
|||
listener, err := net.Listen("tcp", "127.0.0.1:7777") |
|||
if err != nil{ |
|||
fmt.Println("server listen err:", err) |
|||
return |
|||
} |
|||
|
|||
//创建服务器gotoutine,负责从客户端goroutine读取粘包的数据,然后进行解析
|
|||
go func (){ |
|||
for{ |
|||
conn, err := listener.Accept() |
|||
if err != nil{ |
|||
fmt.Println("server accept err:", err) |
|||
} |
|||
|
|||
//处理客户端请求
|
|||
go func(conn net.Conn){ |
|||
//创建封包拆包对象dp
|
|||
dp := NewDataPack() |
|||
for{ |
|||
//1 先读出流中的head部分
|
|||
headData := make([]byte, dp.GetHeadLen()) |
|||
_, err := io.ReadFull(conn, headData) //ReadFull 会把msg填充满为止
|
|||
if err != nil { |
|||
fmt.Println("read head error") |
|||
} |
|||
//将headData字节流 拆包到msg中
|
|||
msgHead,err := dp.Unpack(headData) |
|||
if err != nil{ |
|||
fmt.Println("server unpack err:", err) |
|||
return |
|||
} |
|||
|
|||
if msgHead.GetDataLen() > 0 { |
|||
//msg 是有data数据的,需要再次读取data数据
|
|||
msg := msgHead.(*Message) |
|||
msg.Data = make([]byte, msg.GetDataLen()) |
|||
|
|||
//根据dataLen从io中读取字节流
|
|||
_, err := io.ReadFull(conn, msg.Data) |
|||
if err != nil { |
|||
fmt.Println("server unpack data err:", err) |
|||
return |
|||
} |
|||
|
|||
fmt.Println("==> Recv Msg: ID=", msg.Id, ", len=", msg.DataLen, ", data=", string(msg.Data)) |
|||
} |
|||
} |
|||
}(conn) |
|||
|
|||
} |
|||
}() |
|||
|
|||
//客户端goroutine,负责模拟粘包的数据,然后进行发送
|
|||
conn, err := net.Dial("tcp", "127.0.0.1:7777") |
|||
if err != nil{ |
|||
fmt.Println("client dial err:", err) |
|||
return |
|||
} |
|||
|
|||
//创建一个封包对象 dp
|
|||
dp := NewDataPack() |
|||
|
|||
//封装一个msg1包
|
|||
msg1 := &Message{ |
|||
Id:0, |
|||
DataLen:5, |
|||
Data:[]byte{'h', 'e', 'l', 'l', 'o'}, |
|||
} |
|||
|
|||
sendData1, err := dp.Pack(msg1) |
|||
if err!= nil{ |
|||
fmt.Println("client pack msg1 err:", err) |
|||
return |
|||
} |
|||
|
|||
msg2 := &Message{ |
|||
Id:1, |
|||
DataLen:7, |
|||
Data:[]byte{'w', 'o', 'r', 'l', 'd', '!', '!'}, |
|||
} |
|||
sendData2, err := dp.Pack(msg2) |
|||
if err!= nil{ |
|||
fmt.Println("client temp msg2 err:", err) |
|||
return |
|||
} |
|||
|
|||
//将sendData1,和 sendData2 拼接一起,组成粘包
|
|||
sendData1 = append(sendData1, sendData2...) |
|||
|
|||
//向服务器端写数据
|
|||
conn.Write(sendData1) |
|||
|
|||
//客户端阻塞
|
|||
select{} |
|||
} |
@ -0,0 +1,46 @@ |
|||
package znet |
|||
|
|||
type Message struct { |
|||
Id uint32 //消息的ID
|
|||
DataLen uint32 //消息的长度
|
|||
Data []byte //消息的内容
|
|||
} |
|||
|
|||
//创建一个Message消息包
|
|||
func NewMsgPackage(id uint32, data []byte) *Message { |
|||
return &Message{ |
|||
Id: id, |
|||
DataLen: uint32(len(data)), |
|||
Data: data, |
|||
} |
|||
} |
|||
|
|||
//获取消息数据段长度
|
|||
func (msg *Message) GetDataLen() uint32 { |
|||
return msg.DataLen |
|||
} |
|||
|
|||
//获取消息ID
|
|||
func (msg *Message) GetMsgId() uint32 { |
|||
return msg.Id |
|||
} |
|||
|
|||
//获取消息内容
|
|||
func (msg *Message) GetData() []byte { |
|||
return msg.Data |
|||
} |
|||
|
|||
//设置消息数据段长度
|
|||
func (msg *Message) SetDataLen(len uint32) { |
|||
msg.DataLen = len |
|||
} |
|||
|
|||
//设计消息ID
|
|||
func (msg *Message) SetMsgId(msgId uint32) { |
|||
msg.Id = msgId |
|||
} |
|||
|
|||
//设计消息内容
|
|||
func (msg *Message) SetData(data []byte) { |
|||
msg.Data = data |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue