分享
  1. 首页
  2. 文章

Golang1.7闲来无事写了一个基于Gob的tcp通讯用的包

fyxichen · · 1622 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

package gobconn
import (
 "encoding/gob"
 "errors"
 "net"
 "reflect"
 "sync"
 "unsafe"
)
type message struct {
 Type string
 value reflect.Value
}
func (self message) Recovery() {
 putPointer(self.value)
 putMsg(self)
}
func (self message) Interface() interface{} {
 return self.value.Elem().Interface()
}
/*
声明一个消息池用来重用对象
*/
var msgPool sync.Pool
func getMsg() message {
 if msg, ok := msgPool.Get().(message); ok {
 return msg
 }
 return message{}
}
func putMsg(msg message) {
 msgPool.Put(msg)
}
type gobConnection struct {
 rwc net.Conn
 enc *gob.Encoder
 dec *gob.Decoder
 rlock sync.Mutex
 wlock sync.Mutex
}
type GobConnection interface {
 Read() (msg message, err error)
 Write(msg interface{}) (err error)
 Close() error
 LocalAddr() net.Addr
 RemoteAddr() net.Addr
}
var gobPool sync.Pool
func NewGobConnection(conn net.Conn) GobConnection {
 if gcn, ok := gobPool.Get().(*gobConnection); ok {
 gcn.rwc = conn
 gcn.enc = gob.NewEncoder(conn)
 gcn.dec = gob.NewDecoder(conn)
 return gcn
 }
 return &gobConnection{rwc: conn, enc: gob.NewEncoder(conn), dec: gob.NewDecoder(conn)}
}
type msgStruct struct {
 StructName string
}
var (
 rheadMsg = msgStruct{}
 wheadMsg = msgStruct{}
)
func (self *gobConnection) Read() (msg message, err error) {
 self.rlock.Lock()
 defer self.rlock.Unlock()
 err = self.dec.Decode(&rheadMsg)
 if err != nil {
 return
 }
 var typ reflect.Type
 typ, err = GetMsgType(rheadMsg.StructName)
 if err != nil {
 return
 }
 msg = getMsg()
 msg.Type = rheadMsg.StructName
 var value = getPointer(typ)
 err = self.dec.DecodeValue(value)
 if err != nil {
 msg.Recovery()
 return
 }
 msg.value = value
 return
}
func (self *gobConnection) Write(msg interface{}) (err error) {
 self.wlock.Lock()
 value := reflect.ValueOf(msg)
 if value.Kind() == reflect.Interface || value.Kind() == reflect.Ptr {
 wheadMsg.StructName = value.Elem().Type().String()
 } else {
 wheadMsg.StructName = value.Type().String()
 }
 err = self.enc.Encode(wheadMsg)
 if err != nil {
 self.wlock.Unlock()
 return
 }
 err = self.enc.EncodeValue(value)
 self.wlock.Unlock()
 return
}
func (self *gobConnection) Close() error {
 self.enc = nil
 self.dec = nil
 err := self.rwc.Close()
 gobPool.Put(self)
 return err
}
func (self *gobConnection) LocalAddr() net.Addr {
 return self.rwc.LocalAddr()
}
func (self *gobConnection) RemoteAddr() net.Addr {
 return self.rwc.RemoteAddr()
}
/*
通过指定类型申请一个定长的内存.
*/
var (
 lock sync.Mutex
 ptrMap = make(map[string]*sync.Pool)
)
func getPointer(typ reflect.Type) reflect.Value {
 p, ok := ptrMap[typ.String()]
 if ok {
 if value, ok := p.Get().(reflect.Value); ok {
 return value
 }
 return reflect.New(typ)
 }
 lock.Lock()
 ptrMap[typ.String()] = new(sync.Pool)
 lock.Unlock()
 return reflect.New(typ)
}
func putPointer(value reflect.Value) {
 elem := value.Elem().Type()
 p, ok := ptrMap[elem.String()]
 if !ok {
 lock.Lock()
 p = new(sync.Pool)
 ptrMap[elem.String()] = p
 lock.Unlock()
 }
 ClearData(elem.Size(), unsafe.Pointer(value.Pointer()))
 p.Put(value)
}
/*
 使用此包进行数据发送之前必须将类型注册.否则接收放无法解包
*/
var (
 typeMap = make(map[string]reflect.Type)
 Errortype = errors.New("type not register")
)
func GetMsgType(name string) (reflect.Type, error) {
 typ, ok := typeMap[name]
 if ok {
 return typ, nil
 }
 return nil, Errortype
}
func GetMsgAllType() []string {
 list := make([]string, 0, len(typeMap))
 for name, _ := range typeMap {
 list = append(list, name)
 }
 return list
}
func RegisterType(typ reflect.Type) {
 typeMap[typ.String()] = typ
}
func DeleteType(name string) {
 delete(typeMap, name)
}
/*
清除固定长度的内存数据,使用方法是:指定内存开始地址,和长度.
请勿随便使用.使用不当可能会清除有效数据
*/
func ClearData(size uintptr, ptr unsafe.Pointer) {
 var temptr uintptr = uintptr(ptr)
 var step uintptr = 1
 for {
 if size <= 0 {
 break
 }
 switch {
 case 1 <= size && size < 8:
 step = 1
 case 8 <= size && size < 32:
 step = 8
 case 32 <= size && size < 64:
 step = 32
 case size >= 64:
 step = 64
 }
 clearData(step, unsafe.Pointer(temptr))
 temptr += step
 size -= step
 }
}
func clearData(size uintptr, ptr unsafe.Pointer) {
 switch size {
 case 1:
 *(*[1]byte)(ptr) = [1]byte{}
 case 8:
 *(*[8]byte)(ptr) = [8]byte{}
 case 32:
 *(*[32]byte)(ptr) = [32]byte{}
 case 64:
 *(*[64]byte)(ptr) = [64]byte{}
 }
}

有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:fyxichen

查看原文:Golang1.7闲来无事写了一个基于Gob的tcp通讯用的包

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1622 次点击
1 回复 | 直到 1999年12月31日 16:00:00
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏