Golang1.7闲来无事写了一个基于Gob的tcp通讯用的包
2016-08-26 17:36
459 查看
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{} } }
相关文章推荐
- 闲来无事,写个基于UDP协议的Socket通讯Demo
- 闲来无事,写个基于UDP协议的Socket通讯Demo
- 闲来无事,写个基于TCP协议的Socket通讯Demo
- 浅析H5中的WebSocket对象,创建 一个基于node的TCP网络协议的通讯协议
- 闲来无事写的一个简单的JavaScript日历
- 使用Net类库,实现的基于TCP/IP简单的通讯框架框架(一)
- 模拟一个简单的基于tcp的远程关机程序
- ios实现基于socket tcp/ip 的通讯
- 【socket编程】一个简单的基于TCP的客户/服务端例子(vs2008)
- ios实现基于socket tcp/ip 的通讯
- 基于TCP的通讯程序 进行封包和拆包二
- 基于TCP的通讯程序 进行封包和拆包一
- 一个winform的基于TCP的服务端的GPS平台的网关。利用多线程异步的方式 。
- 一个完整的TCP通讯流程(转)
- 怎样写一个获取数据函数:用TCP/IP通讯,向服务端发送命令,并从服务端获得返回数据.
- 基于TCP的网络通讯一段时间后出现断网问题
- 我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯
- 基于qt的一个tcp通信小程序
- 我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯
- ios实现基于socket tcp/ip 的通讯