丰乐

go脚手架link源码分析

一直觉得这是个非常优秀的项目,非常精练,值得一读。

 昨天下班特意画一个小时读了一遍,代码非常短,使用go做网络开发的同学可以读一下。

短小精悍,今天特写写了一篇博客介绍下。读起来特别开心。针对。

 

项目地址

https://github.com/funny/link 

项目的使用,从官网抄的

package main

import (
    "log"
    "net"

    "github.com/funny/link"
    "github.com/funny/link/codec"
)

type AddReq struct {
    A, B int
}

type AddRsp struct {
    C int
}

type Server struct{}

func main() {
    json := codec.Json()
    json.Register(AddReq{})
    json.Register(AddRsp{})

    listen, err := net.Listen("tcp", "")
    checkErr(err)
    server := link.NewServer(listen, json, 1024, new(Server))
    go server.Serve()
    addr := server.Listener().Addr()

    clientSession, err := link.Dial(addr.Network(), addr.String(), json, 1024)
    checkErr(err)
    clientSessionLoop(clientSession)
}

func (*Server) HandleSession(session *link.Session) {
    for {
        req, err := session.Receive()
        checkErr(err)

        err = session.Send(&AddRsp{
            req.(*AddReq).A + req.(*AddReq).B,
        })
        checkErr(err)
    }
}

func clientSessionLoop(session *link.Session) {
    for i := 0; i < 10; i++ {
        err := session.Send(&AddReq{
            i, i,
        })
        checkErr(err)
        log.Printf("Send: %d + %d", i, i)

        rsp, err := session.Receive()
        checkErr(err)
        log.Printf("Receive: %d", rsp.(*AddRsp).C)
    }
}

func checkErr(err error) {
    if err != nil {
        log.Fatal(err)
    }
}
View Code

 

项目的主体结构分析

 

1  Protocol 接口,主要通过接受io.ReadWriter接口参数,创建协议解析器

2 ProtocolFunc 定义函数类型,处理rw io.ReadWrite和返回Codec,err的都可以使用

3 Accept 接受tcp连接,这部分抄了net.http的包

4 Server是读Session请求的转发

type Server struct {
    manager      *Manager //session管理器
    listener     net.Listener //网络连接
    protocol     Protocol //协议解析器
    handler      Handler//session处理器
    sendChanSize int//发送chan的大小
}

5  manager对session进行了统一管理,还进行了分片

6 session 处理网络请求的支持同步和异步两种方式

//sessionId
var globalSessionId uint64

type Session struct {
    id        uint64  //id
    codec     Codec   //解析器
    manager   *Manager //管理器
    sendChan  chan interface{}//发送通道
    recvMutex sync.Mutex //接收的锁
    sendMutex sync.RWMutex//发送的锁

    closeFlag          int32 //关闭flag
    closeChan          chan int//关闭的chan
    closeMutex         sync.Mutex//关闭的锁
    firstCloseCallback *closeCallback//初次关闭的回调
    lastCloseCallback  *closeCallback//最后关闭的回调

    State interface{}//状态
}

 

7 协议定义实现 codec的都能被封装

//定义协议接口
type Protocol interface {
NewCodec(rw io.ReadWriter) (Codec, error)
}

// 协议接口的实现函数
type ProtocolFunc func(rw io.ReadWriter) (Codec, error)
func (pf ProtocolFunc) NewCodec(rw io.ReadWriter) (Codec, error) {
return pf(rw)
}

//解析器接口 1 接收 2 发送 3 关闭
type Codec interface {
Receive() (interface{}, error)
Send(interface{}) error
Close() error
}

//清理关闭chan的接口
type ClearSendChan interface {
ClearSendChan(<-chan interface{})
}

 

8 channel主要对session进行一些操作

//chanel的状态
type Channel struct {
    mutex    sync.RWMutex
    sessions map[KEY]*Session

    // channel state
    State interface{}
}

 

大体执行流程是

  1 创建协议

  2 定义session的处理方法

  3 监听请求,建立session,对session进行处理,监听请求

  4 接收请求的数据通过codec去处理,处理完毕关闭session调用session回调

  5 可以通过Chan发送广播之类的操作

 

posted on 2019-09-06 23:12  李蝉儿  阅读(581)  评论(0编辑  收藏  举报

导航