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

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{}
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用golang中的net库和raw socket来构造一个TCP SYN并添加TCP选项字段。以下是一个示例代码: ```go package main import ( "net" "syscall" ) func main() { // 构造TCP SYN srcIP := net.ParseIP("192.168.1.100") dstIP := net.ParseIP("192.168.1.1") srcPort := 12345 dstPort := 80 seqNum := uint32(123456789) tcpHeaderLen := 20 tcpFlags := syscall.TCP_SYN // 构造TCP选项字段 tcpOptions := []byte{0x02, 0x04, 0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x00, 0x0f, 0x48, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x57, 0x65, 0x62, 0x21} // 构造TCP头部 tcpHeader := make([]byte, tcpHeaderLen) tcpHeader[0] = byte(srcPort >> 8) tcpHeader[1] = byte(srcPort) tcpHeader[2] = byte(dstPort >> 8) tcpHeader[3] = byte(dstPort) tcpHeader[4] = byte(seqNum >> 24) tcpHeader[5] = byte(seqNum >> 16) tcpHeader[6] = byte(seqNum >> 8) tcpHeader[7] = byte(seqNum) tcpHeader[8] = byte(0) tcpHeader[9] = byte(0) tcpHeader[10] = byte(tcpHeaderLen >> 8) tcpHeader[11] = byte(tcpHeaderLen) tcpHeader[13] = byte(tcpFlags) tcpHeader[14] = byte(0x10) tcpHeader[15] = byte(0xff) // 添加TCP选项字段 copy(tcpHeader[tcpHeaderLen:], tcpOptions) // 构造IP头部 ipHeaderLen := 20 ipVersion := 4 ipHeader := make([]byte, ipHeaderLen) ipHeader[0] = byte(ipVersion<<4 | ipHeaderLen>>2) ipHeader[1] = byte(0) ipHeader[2] = byte(0) ipHeader[3] = byte(0) ipHeader[4] = byte(0) ipHeader[5] = byte(0) ipHeader[6] = byte(0) ipHeader[7] = byte(0) ipHeader[8] = byte(0) ipHeader[9] = byte(0) ipHeader[10] = byte(0xff) ipHeader[11] = byte(0xff) copy(ipHeader[12:16], srcIP.To4()) copy(ipHeader[16:20], dstIP.To4()) // 计算IP头部校验和 checksum := checksum(ipHeader) // 添加IP头部校验和 ipHeader[10] = byte(checksum >> 8) ipHeader[11] = byte(checksum) // 合并IP和TCP头部 packet := make([]byte, len(ipHeader)+len(tcpHeader)) copy(packet, ipHeader) copy(packet[len(ipHeader):], tcpHeader) // 发送TCP SYN conn, err := net.Dial("ip4:tcp", dstIP.String()) if err != nil { panic(err) } defer conn.Close() _, err = conn.Write(packet) if err != nil { panic(err) } } // 计算校验和 func checksum(data []byte) uint16 { var sum uint32 for i := 0; i < len(data)-1; i += 2 { sum += uint32(data[i])<<8 | uint32(data[i+1]) } if len(data)%2 != 0 { sum += uint32(data[len(data)-1]) << 8 } for (sum >> 16) > 0 { sum = (sum & 0xffff) + (sum >> 16) } return ^uint16(sum) } ``` 这段代码构造了一个源IP为192.168.1.100,目标IP为192.168.1.1,源端口为12345,目标端口为80的TCP SYN,并添加了TCP选项字段。在发送之前,需要使用`net.Dial("ip4:tcp", dstIP.String())`连接到目标IP地址,然后将构造好的TCP SYN入连接中即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值