other: server/v2 基本通讯模型实现
This commit is contained in:
parent
5b0ea566d5
commit
89e868bd1c
|
@ -1,3 +0,0 @@
|
||||||
package server
|
|
||||||
|
|
||||||
type
|
|
|
@ -1,7 +0,0 @@
|
||||||
package actor
|
|
||||||
|
|
||||||
import "github.com/kercylan98/minotaur/server/internal/v2/dispatcher"
|
|
||||||
|
|
||||||
type Actor[M any] struct {
|
|
||||||
*dispatcher.Dispatcher[M]
|
|
||||||
}
|
|
|
@ -1,26 +1,58 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"github.com/kercylan98/minotaur/server/internal/v2/dispatcher"
|
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnWriter func(packet Packet) error
|
type ConnWriter func(packet Packet) error
|
||||||
|
|
||||||
type Conn interface {
|
type Conn interface {
|
||||||
|
// SetActor 设置连接使用的 Actor 名称
|
||||||
|
SetActor(actor string)
|
||||||
|
|
||||||
|
// GetActor 获取连接使用的 Actor 名称
|
||||||
|
GetActor() string
|
||||||
|
|
||||||
|
// WritePacket 写入一个 Packet
|
||||||
|
WritePacket(packet Packet) error
|
||||||
|
|
||||||
|
// Write 写入数据
|
||||||
|
Write(data []byte) (n int, err error)
|
||||||
|
|
||||||
|
// WriteBytes 写入数据
|
||||||
|
WriteBytes(data []byte) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConn(ctx context.Context, c net.Conn, connWriter ConnWriter) Conn {
|
func newConn(c net.Conn, connWriter ConnWriter) *conn {
|
||||||
return &conn{
|
return &conn{
|
||||||
conn: c,
|
conn: c,
|
||||||
writer: connWriter,
|
writer: connWriter,
|
||||||
actor: dispatcher.NewActor[Packet](ctx, handler),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type conn struct {
|
type conn struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
writer ConnWriter
|
writer ConnWriter
|
||||||
actor *dispatcher.Actor[Packet]
|
actor string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) SetActor(actor string) {
|
||||||
|
c.actor = actor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) GetActor() string {
|
||||||
|
return c.actor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) WritePacket(packet Packet) error {
|
||||||
|
return c.writer(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) Write(data []byte) (n int, err error) {
|
||||||
|
return c.conn.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) WriteBytes(data []byte) error {
|
||||||
|
_, err := c.conn.Write(data)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,23 +3,51 @@ package server
|
||||||
import "net"
|
import "net"
|
||||||
|
|
||||||
type Controller interface {
|
type Controller interface {
|
||||||
Run() error
|
RegisterConnection(conn net.Conn, writer ConnWriter)
|
||||||
Shutdown() error
|
EliminateConnection(conn net.Conn, err error)
|
||||||
|
ReactPacket(conn net.Conn, packet Packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
type controller struct {
|
type controller struct {
|
||||||
*server
|
*server
|
||||||
|
connections map[net.Conn]*conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *controller) init(srv *server) *controller {
|
func (s *controller) init(srv *server) *controller {
|
||||||
s.server = srv
|
s.server = srv
|
||||||
|
s.connections = make(map[net.Conn]*conn)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *controller) RegisterConn(conn net.Conn, writer ConnWriter) {
|
func (s *controller) RegisterConnection(conn net.Conn, writer ConnWriter) {
|
||||||
|
if err := s.server.reactor.SystemDispatch(HandlerMessage(s.server, func(srv *server) {
|
||||||
|
srv.connections[conn] = newConn(conn, writer)
|
||||||
|
})); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *controller) UnRegisterConn() {
|
func (s *controller) EliminateConnection(conn net.Conn, err error) {
|
||||||
|
if err := s.server.reactor.SystemDispatch(HandlerMessage(s.server, func(srv *server) {
|
||||||
|
delete(srv.connections, conn)
|
||||||
|
})); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *controller) ReactPacket(conn net.Conn, packet Packet) {
|
||||||
|
if err := s.server.reactor.SystemDispatch(HandlerMessage(s.server, func(srv *server) {
|
||||||
|
c, exist := srv.connections[conn]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := srv.reactor.Dispatch(c.GetActor(), HandlerMessage(srv, func(srv *server) {
|
||||||
|
srv.events.onConnectionReceivePacket(c, packet)
|
||||||
|
})); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
})); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
package dispatcher
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"github.com/kercylan98/minotaur/utils/buffer"
|
|
||||||
"github.com/kercylan98/minotaur/utils/log"
|
|
||||||
"github.com/kercylan98/minotaur/utils/super"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDispatcher 创建一个消息调度器
|
|
||||||
func NewDispatcher[M any](bufferSize int, handler func(M)) *Dispatcher[M] {
|
|
||||||
d := &Dispatcher[M]{
|
|
||||||
buf: buffer.NewRing[M](bufferSize),
|
|
||||||
bufCond: sync.NewCond(&sync.Mutex{}),
|
|
||||||
ctx: context.Background(),
|
|
||||||
}
|
|
||||||
|
|
||||||
d.BindErrorHandler(func(err error) {
|
|
||||||
log.Error("dispatcher", log.Err(err))
|
|
||||||
})
|
|
||||||
|
|
||||||
d.handler = func(m M) {
|
|
||||||
defer func() {
|
|
||||||
if err := super.RecoverTransform(recover()); err != nil {
|
|
||||||
d.errorHandler.Load().(func(error))(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
handler(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispatcher 并发安全且不阻塞的消息调度器
|
|
||||||
type Dispatcher[M any] struct {
|
|
||||||
buf *buffer.Ring[M]
|
|
||||||
bufCond *sync.Cond
|
|
||||||
handler func(M)
|
|
||||||
closed bool
|
|
||||||
ctx context.Context
|
|
||||||
errorHandler atomic.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindErrorHandler 绑定一个错误处理器到调度器中
|
|
||||||
func (d *Dispatcher[M]) BindErrorHandler(handler func(error)) {
|
|
||||||
d.errorHandler.Store(handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// BindContext 绑定一个上下文到调度器中
|
|
||||||
func (d *Dispatcher[M]) BindContext(ctx context.Context) {
|
|
||||||
d.bufCond.L.Lock()
|
|
||||||
d.ctx = ctx
|
|
||||||
if _, canceled := d.ctx.Deadline(); canceled {
|
|
||||||
d.closed = true
|
|
||||||
d.bufCond.Signal()
|
|
||||||
d.bufCond.L.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.bufCond.L.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send 发送消息到调度器中等待处理
|
|
||||||
func (d *Dispatcher[M]) Send(m M) error {
|
|
||||||
d.bufCond.L.Lock()
|
|
||||||
if d.closed {
|
|
||||||
d.bufCond.L.Unlock()
|
|
||||||
return errors.New("dispatcher closed")
|
|
||||||
}
|
|
||||||
d.buf.Write(m)
|
|
||||||
d.bufCond.Signal()
|
|
||||||
d.bufCond.L.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start 阻塞式启动调度器,调用后将开始处理消息
|
|
||||||
func (d *Dispatcher[M]) Start() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-d.ctx.Done():
|
|
||||||
d.Stop()
|
|
||||||
default:
|
|
||||||
d.bufCond.L.Lock()
|
|
||||||
if d.buf.Len() == 0 {
|
|
||||||
if d.closed {
|
|
||||||
d.bufCond.L.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.bufCond.Wait()
|
|
||||||
}
|
|
||||||
messages := d.buf.ReadAll()
|
|
||||||
d.bufCond.L.Unlock()
|
|
||||||
for _, msg := range messages {
|
|
||||||
d.handler(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop 停止调度器,调用后将不再接受新消息,但会处理完已有消息
|
|
||||||
func (d *Dispatcher[M]) Stop() {
|
|
||||||
d.bufCond.L.Lock()
|
|
||||||
d.closed = true
|
|
||||||
d.bufCond.Signal()
|
|
||||||
d.bufCond.L.Unlock()
|
|
||||||
}
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import "github.com/kercylan98/minotaur/utils/collection/listings"
|
||||||
|
|
||||||
|
type (
|
||||||
|
ConnectionReceivePacketEventHandler func(srv Server, conn Conn, packet Packet)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Events interface {
|
||||||
|
RegisterConnectionReceivePacketEvent(handler ConnectionReceivePacketEventHandler, priority ...int)
|
||||||
|
}
|
||||||
|
|
||||||
|
type events struct {
|
||||||
|
*server
|
||||||
|
|
||||||
|
connectionReceivePacketEventHandlers listings.PrioritySlice[ConnectionReceivePacketEventHandler]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *events) init(srv *server) *events {
|
||||||
|
s.server = srv
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *events) RegisterConnectionReceivePacketEvent(handler ConnectionReceivePacketEventHandler, priority ...int) {
|
||||||
|
s.connectionReceivePacketEventHandlers.AppendByOptionalPriority(handler, priority...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *events) onConnectionReceivePacket(conn Conn, packet Packet) {
|
||||||
|
s.connectionReceivePacketEventHandlers.RangeValue(func(index int, value ConnectionReceivePacketEventHandler) bool {
|
||||||
|
value(s.server, conn, packet)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
type Message interface {
|
||||||
|
Execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandlerMessage(srv *server, handler func(srv *server)) Message {
|
||||||
|
return &handlerMessage{srv: srv, handler: handler}
|
||||||
|
}
|
||||||
|
|
||||||
|
type handlerMessage struct {
|
||||||
|
srv *server
|
||||||
|
handler func(srv *server)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *handlerMessage) Execute() {
|
||||||
|
s.handler(s.srv)
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Http(addr string) server.server {
|
func Http(addr string) server.Network {
|
||||||
return HttpWithHandler(addr, &HttpServe{ServeMux: http.NewServeMux()})
|
return HttpWithHandler(addr, &HttpServe{ServeMux: http.NewServeMux()})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +30,11 @@ type httpCore[H http.Handler] struct {
|
||||||
addr string
|
addr string
|
||||||
handler H
|
handler H
|
||||||
srv *http.Server
|
srv *http.Server
|
||||||
event server.NetworkCore
|
controller server.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpCore[H]) OnSetup(ctx context.Context, event server.NetworkCore) (err error) {
|
func (h *httpCore[H]) OnSetup(ctx context.Context, controller server.Controller) (err error) {
|
||||||
h.event = event
|
h.controller = controller
|
||||||
h.srv.BaseContext = func(listener net.Listener) context.Context {
|
h.srv.BaseContext = func(listener net.Listener) context.Context {
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func WebSocket(addr string, pattern ...string) server.server {
|
func WebSocket(addr string, pattern ...string) server.Network {
|
||||||
ws := &websocketCore{
|
ws := &websocketCore{
|
||||||
addr: addr,
|
addr: addr,
|
||||||
pattern: collection.FindFirstOrDefaultInSlice(pattern, "/"),
|
pattern: collection.FindFirstOrDefaultInSlice(pattern, "/"),
|
||||||
|
@ -19,16 +19,16 @@ func WebSocket(addr string, pattern ...string) server.server {
|
||||||
|
|
||||||
type websocketCore struct {
|
type websocketCore struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
core server.NetworkCore
|
controller server.Controller
|
||||||
handler *websocketHandler
|
handler *websocketHandler
|
||||||
addr string
|
addr string
|
||||||
pattern string
|
pattern string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *websocketCore) OnSetup(ctx context.Context, core server.NetworkCore) (err error) {
|
func (w *websocketCore) OnSetup(ctx context.Context, controller server.Controller) (err error) {
|
||||||
w.ctx = ctx
|
w.ctx = ctx
|
||||||
w.handler = newWebsocketHandler(w)
|
w.handler = newWebsocketHandler(w)
|
||||||
w.core = core
|
w.controller = controller
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,14 +12,14 @@ import (
|
||||||
|
|
||||||
func newWebsocketHandler(core *websocketCore) *websocketHandler {
|
func newWebsocketHandler(core *websocketCore) *websocketHandler {
|
||||||
return &websocketHandler{
|
return &websocketHandler{
|
||||||
core: core,
|
websocketCore: core,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type websocketHandler struct {
|
type websocketHandler struct {
|
||||||
engine *gnet.Engine
|
engine *gnet.Engine
|
||||||
upgrader ws.Upgrader
|
upgrader ws.Upgrader
|
||||||
core *websocketCore
|
*websocketCore
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *websocketHandler) OnBoot(eng gnet.Engine) (action gnet.Action) {
|
func (w *websocketHandler) OnBoot(eng gnet.Engine) (action gnet.Action) {
|
||||||
|
@ -33,17 +33,16 @@ func (w *websocketHandler) OnShutdown(eng gnet.Engine) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *websocketHandler) OnOpen(c gnet.Conn) (out []byte, action gnet.Action) {
|
func (w *websocketHandler) OnOpen(c gnet.Conn) (out []byte, action gnet.Action) {
|
||||||
wrapper := newWebsocketWrapper(w.core.ctx, c)
|
wrapper := newWebsocketWrapper(c)
|
||||||
c.SetContext(wrapper)
|
c.SetContext(wrapper)
|
||||||
w.core.core.OnConnectionOpened(wrapper.ctx, c, func(message server.server) error {
|
w.controller.RegisterConnection(c, func(packet server.Packet) error {
|
||||||
return wsutil.WriteServerMessage(c, message.GetContext().(ws.OpCode), message.GetBytes())
|
return wsutil.WriteServerMessage(c, packet.GetContext().(ws.OpCode), packet.GetBytes())
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *websocketHandler) OnClose(c gnet.Conn, err error) (action gnet.Action) {
|
func (w *websocketHandler) OnClose(c gnet.Conn, err error) (action gnet.Action) {
|
||||||
wrapper := c.Context().(*websocketWrapper)
|
w.controller.EliminateConnection(c, err)
|
||||||
wrapper.cancel()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,9 +69,9 @@ func (w *websocketHandler) OnTraffic(c gnet.Conn) (action gnet.Action) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, message := range messages {
|
for _, message := range messages {
|
||||||
packet := w.core.core.GeneratePacket(message.Payload)
|
packet := server.NewPacket(message.Payload)
|
||||||
packet.SetContext(message.OpCode)
|
packet.SetContext(message.OpCode)
|
||||||
w.core.core.OnReceivePacket(packet)
|
w.controller.ReactPacket(c, packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -85,7 +84,7 @@ func (w *websocketHandler) OnTick() (delay time.Duration, action gnet.Action) {
|
||||||
func (w *websocketHandler) initUpgrader() {
|
func (w *websocketHandler) initUpgrader() {
|
||||||
w.upgrader = ws.Upgrader{
|
w.upgrader = ws.Upgrader{
|
||||||
OnRequest: func(uri []byte) (err error) {
|
OnRequest: func(uri []byte) (err error) {
|
||||||
if string(uri) != w.core.pattern {
|
if string(uri) != w.pattern {
|
||||||
err = errors.New("bad request")
|
err = errors.New("bad request")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
@ -8,26 +8,22 @@ import (
|
||||||
"github.com/gobwas/ws/wsutil"
|
"github.com/gobwas/ws/wsutil"
|
||||||
"github.com/kercylan98/minotaur/utils/super"
|
"github.com/kercylan98/minotaur/utils/super"
|
||||||
"github.com/panjf2000/gnet/v2"
|
"github.com/panjf2000/gnet/v2"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newWebsocketWrapper 创建 websocket 包装器
|
// newWebsocketWrapper 创建 websocket 包装器
|
||||||
func newWebsocketWrapper(ctx context.Context, conn gnet.Conn) *websocketWrapper {
|
func newWebsocketWrapper(conn gnet.Conn) *websocketWrapper {
|
||||||
wrapper := &websocketWrapper{
|
wrapper := &websocketWrapper{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
upgraded: false,
|
upgraded: false,
|
||||||
active: time.Now(),
|
active: time.Now(),
|
||||||
}
|
}
|
||||||
wrapper.ctx, wrapper.cancel = context.WithCancel(ctx)
|
|
||||||
return wrapper
|
return wrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
// websocketWrapper websocket 包装器
|
// websocketWrapper websocket 包装器
|
||||||
type websocketWrapper struct {
|
type websocketWrapper struct {
|
||||||
ctx context.Context
|
|
||||||
cancel context.CancelFunc
|
|
||||||
conn gnet.Conn // 连接
|
conn gnet.Conn // 连接
|
||||||
upgraded bool // 是否已经升级
|
upgraded bool // 是否已经升级
|
||||||
hs ws.Handshake // 握手信息
|
hs ws.Handshake // 握手信息
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
|
func NewPacket(data []byte) Packet {
|
||||||
|
return new(packet).init(data)
|
||||||
|
}
|
||||||
|
|
||||||
type Packet interface {
|
type Packet interface {
|
||||||
GetBytes() []byte
|
GetBytes() []byte
|
||||||
SetContext(ctx any)
|
SetContext(ctx any) Packet
|
||||||
GetContext() any
|
GetContext() any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +29,9 @@ func (m *packet) GetBytes() []byte {
|
||||||
return m.data
|
return m.data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *packet) SetContext(ctx any) {
|
func (m *packet) SetContext(ctx any) Packet {
|
||||||
m.ctx = ctx
|
m.ctx = ctx
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *packet) GetContext() any {
|
func (m *packet) GetContext() any {
|
||||||
|
|
|
@ -1,17 +1,24 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import "golang.org/x/net/context"
|
import (
|
||||||
|
"github.com/kercylan98/minotaur/server/internal/v2/reactor"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
type Server interface {
|
type Server interface {
|
||||||
|
Events
|
||||||
|
|
||||||
Run() error
|
Run() error
|
||||||
Shutdown() error
|
Shutdown() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type server struct {
|
type server struct {
|
||||||
*controller
|
*controller
|
||||||
|
*events
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
network Network
|
network Network
|
||||||
|
reactor *reactor.Reactor[Message]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(network Network) Server {
|
func NewServer(network Network) Server {
|
||||||
|
@ -20,10 +27,15 @@ func NewServer(network Network) Server {
|
||||||
}
|
}
|
||||||
srv.ctx, srv.cancel = context.WithCancel(context.Background())
|
srv.ctx, srv.cancel = context.WithCancel(context.Background())
|
||||||
srv.controller = new(controller).init(srv)
|
srv.controller = new(controller).init(srv)
|
||||||
|
srv.events = new(events).init(srv)
|
||||||
|
srv.reactor = reactor.NewReactor[Message](1024*8, 1024, func(msg Message) {
|
||||||
|
msg.Execute()
|
||||||
|
}, nil)
|
||||||
return srv
|
return srv
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) Run() (err error) {
|
func (s *server) Run() (err error) {
|
||||||
|
go s.reactor.Run()
|
||||||
if err = s.network.OnSetup(s.ctx, s); err != nil {
|
if err = s.network.OnSetup(s.ctx, s); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -35,7 +47,8 @@ func (s *server) Run() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) Shutdown() (err error) {
|
func (s *server) Shutdown() (err error) {
|
||||||
defer s.server.cancel()
|
defer s.cancel()
|
||||||
err = s.network.OnShutdown()
|
err = s.network.OnShutdown()
|
||||||
|
s.reactor.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewServer(t *testing.T) {
|
func TestNewServer(t *testing.T) {
|
||||||
srv := server.server.NewServer(network.WebSocket(":9999"))
|
srv := server.NewServer(network.WebSocket(":9999"))
|
||||||
|
srv.RegisterConnectionReceivePacketEvent(func(srv server.Server, conn server.Conn, packet server.Packet) {
|
||||||
|
if err := conn.WritePacket(packet); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
if err := srv.Run(); err != nil {
|
if err := srv.Run(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue