gf/g/net/gtcp/gtcp_conn_pkg.go

155 lines
4.7 KiB
Go
Raw Normal View History

2019-04-28 23:55:23 +08:00
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gtcp
import (
"encoding/binary"
"fmt"
"time"
2019-06-22 22:05:39 +08:00
2019-06-29 23:35:32 +08:00
"github.com/gogf/gf/g/errors/gerror"
2019-04-28 23:55:23 +08:00
)
const (
2019-05-20 08:59:16 +08:00
// 默认允许最大的简单协议包大小(byte), 65535 byte
2019-06-03 23:53:59 +08:00
gPKG_MAX_DATA_SIZE = 65535
// 简单协议包头大小
2019-06-19 09:06:52 +08:00
gPKG_HEADER_SIZE = 3
2019-04-28 23:55:23 +08:00
)
2019-05-20 08:59:16 +08:00
// 数据读取选项
2019-06-03 23:53:59 +08:00
type PkgOption struct {
2019-06-19 09:06:52 +08:00
MaxSize int // (byte)数据读取的最大包大小最大不能超过3字节(0xFFFFFF,15MB)默认为65535byte
Retry Retry // 失败重试
2019-05-20 08:59:16 +08:00
}
2019-06-03 23:53:59 +08:00
// getPkgOption wraps and returns the PkgOption.
2019-05-20 08:59:16 +08:00
// If no option given, it returns a new option with default value.
2019-06-19 09:06:52 +08:00
func getPkgOption(option ...PkgOption) (*PkgOption, error) {
2019-06-03 23:53:59 +08:00
pkgOption := PkgOption{}
2019-05-20 08:59:16 +08:00
if len(option) > 0 {
pkgOption = option[0]
}
if pkgOption.MaxSize == 0 {
2019-06-03 23:53:59 +08:00
pkgOption.MaxSize = gPKG_MAX_DATA_SIZE
2019-05-20 08:59:16 +08:00
} else if pkgOption.MaxSize > 0xFFFFFF {
return nil, fmt.Errorf(`package size %d exceeds allowed max size %d`, pkgOption.MaxSize, 0xFFFFFF)
}
return &pkgOption, nil
}
2019-04-28 23:55:23 +08:00
// 根据简单协议发送数据包。
2019-06-03 23:53:59 +08:00
//
// 简单协议数据格式:数据长度(24bit)|数据字段(变长)。
//
2019-04-28 23:55:23 +08:00
// 注意:
2019-06-03 23:53:59 +08:00
// 1. "数据长度"仅为"数据字段"的长度不包含头信息的长度字段3字节。
// 2. 由于"数据长度"为3字节并且使用的BigEndian字节序因此这里最后返回的buffer使用了buffer[1:]。
2019-06-19 09:06:52 +08:00
func (c *Conn) SendPkg(data []byte, option ...PkgOption) error {
2019-05-20 08:59:16 +08:00
pkgOption, err := getPkgOption(option...)
if err != nil {
return err
}
length := len(data)
2019-06-03 23:53:59 +08:00
if length > pkgOption.MaxSize {
2019-06-21 22:23:07 +08:00
return fmt.Errorf(`data size %d exceeds max pkg size %d`, length, gPKG_MAX_DATA_SIZE)
2019-05-20 08:59:16 +08:00
}
2019-06-19 09:06:52 +08:00
buffer := make([]byte, gPKG_HEADER_SIZE+1+len(data))
binary.BigEndian.PutUint32(buffer[0:], uint32(length))
copy(buffer[gPKG_HEADER_SIZE+1:], data)
2019-05-20 08:59:16 +08:00
if pkgOption.Retry.Count > 0 {
2019-06-04 23:33:46 +08:00
return c.Send(buffer[1:], pkgOption.Retry)
2019-05-20 08:59:16 +08:00
}
2019-06-03 23:53:59 +08:00
//fmt.Println("SendPkg:", buffer[1:])
2019-05-20 08:59:16 +08:00
return c.Send(buffer[1:])
2019-04-28 23:55:23 +08:00
}
// 简单协议: 带超时时间的数据发送
2019-06-21 22:23:07 +08:00
func (c *Conn) SendPkgWithTimeout(data []byte, timeout time.Duration, option ...PkgOption) (err error) {
2019-06-04 23:33:46 +08:00
if err := c.SetSendDeadline(time.Now().Add(timeout)); err != nil {
return err
}
2019-06-21 22:23:07 +08:00
defer func() {
2019-06-29 23:35:32 +08:00
err = gerror.Wrap(c.SetSendDeadline(time.Time{}), "SetSendDeadline error")
2019-06-21 22:23:07 +08:00
}()
err = c.SendPkg(data, option...)
return
2019-04-28 23:55:23 +08:00
}
// 简单协议: 发送数据并等待接收返回数据
2019-06-19 09:06:52 +08:00
func (c *Conn) SendRecvPkg(data []byte, option ...PkgOption) ([]byte, error) {
2019-05-20 08:59:16 +08:00
if err := c.SendPkg(data, option...); err == nil {
return c.RecvPkg(option...)
2019-04-28 23:55:23 +08:00
} else {
return nil, err
}
}
// 简单协议: 发送数据并等待接收返回数据(带返回超时等待时间)
2019-06-19 09:06:52 +08:00
func (c *Conn) SendRecvPkgWithTimeout(data []byte, timeout time.Duration, option ...PkgOption) ([]byte, error) {
2019-05-20 08:59:16 +08:00
if err := c.SendPkg(data, option...); err == nil {
return c.RecvPkgWithTimeout(timeout, option...)
2019-04-28 23:55:23 +08:00
} else {
return nil, err
}
}
// 简单协议: 获取一个数据包。
2019-06-19 09:06:52 +08:00
func (c *Conn) RecvPkg(option ...PkgOption) (result []byte, err error) {
var temp []byte
2019-05-20 08:59:16 +08:00
var length int
pkgOption, err := getPkgOption(option...)
if err != nil {
return nil, err
}
2019-04-28 23:55:23 +08:00
for {
// 先根据对象的缓冲区数据进行计算
for {
2019-06-03 23:53:59 +08:00
if len(c.buffer) >= gPKG_HEADER_SIZE {
// 注意"数据长度"为3个字节不满足4个字节的uint32类型因此这里"低位"补0
2019-05-20 08:59:16 +08:00
length = int(binary.BigEndian.Uint32([]byte{0, c.buffer[0], c.buffer[1], c.buffer[2]}))
// 解析的大小是否符合规范,清空从该连接接收到的所有数据包
2019-06-03 23:53:59 +08:00
if length < 0 || length > pkgOption.MaxSize {
2019-05-20 08:59:16 +08:00
c.buffer = c.buffer[:0]
return nil, fmt.Errorf(`invalid package size %d`, length)
2019-04-28 23:55:23 +08:00
}
// 不满足包大小,需要继续读取
2019-06-19 09:06:52 +08:00
if len(c.buffer) < length+gPKG_HEADER_SIZE {
2019-04-28 23:55:23 +08:00
break
}
2019-06-19 09:06:52 +08:00
result = c.buffer[gPKG_HEADER_SIZE : gPKG_HEADER_SIZE+length]
c.buffer = c.buffer[gPKG_HEADER_SIZE+length:]
2019-04-28 23:55:23 +08:00
return
} else {
break
}
}
// 读取系统socket缓冲区的完整数据
2019-06-03 23:53:59 +08:00
temp, err = c.Recv(0, pkgOption.Retry)
2019-04-28 23:55:23 +08:00
if err != nil {
break
}
if len(temp) > 0 {
c.buffer = append(c.buffer, temp...)
}
//fmt.Println("RecvPkg:", c.buffer)
2019-04-28 23:55:23 +08:00
}
return
}
// 简单协议: 带超时时间的消息包获取
2019-06-21 22:23:07 +08:00
func (c *Conn) RecvPkgWithTimeout(timeout time.Duration, option ...PkgOption) (data []byte, err error) {
2019-06-04 23:33:46 +08:00
if err := c.SetRecvDeadline(time.Now().Add(timeout)); err != nil {
return nil, err
}
2019-06-21 22:23:07 +08:00
defer func() {
2019-06-29 23:35:32 +08:00
err = gerror.Wrap(c.SetRecvDeadline(time.Time{}), "SetRecvDeadline error")
2019-06-21 22:23:07 +08:00
}()
data, err = c.RecvPkg(option...)
return
2019-06-19 09:06:52 +08:00
}