服务器连接异步读写

This commit is contained in:
kercylan98 2023-05-15 11:49:36 +08:00
parent 926b69bee1
commit b28badbaab
8 changed files with 133 additions and 43 deletions

View File

@ -20,8 +20,8 @@ func (slf *Player[ID]) GetID() ID {
}
// Send 向该玩家发送数据
func (slf *Player[ID]) Send(packet []byte) error {
return slf.conn.Write(packet)
func (slf *Player[ID]) Send(packet []byte, messageType ...int) {
slf.conn.Write(packet, messageType...)
}
// Close 关闭玩家

View File

@ -5,7 +5,8 @@ type Player[ID comparable] interface {
// GetID 用户玩家ID
GetID() ID
// Send 发送数据包
Send(packet []byte) error
// - messageType: websocket模式中指定消息类型
Send(packet []byte, messageType ...int)
// Close 关闭玩家并且释放其资源
Close()
}

View File

@ -9,8 +9,9 @@ import (
)
// newKcpConn 创建一个处理KCP的连接
func newKcpConn(session *kcp.UDPSession) *Conn {
func newKcpConn(server *Server, session *kcp.UDPSession) *Conn {
c := &Conn{
server: server,
remoteAddr: session.RemoteAddr(),
ip: session.RemoteAddr().String(),
kcp: session,
@ -27,8 +28,9 @@ func newKcpConn(session *kcp.UDPSession) *Conn {
}
// newKcpConn 创建一个处理GNet的连接
func newGNetConn(conn gnet.Conn) *Conn {
func newGNetConn(server *Server, conn gnet.Conn) *Conn {
c := &Conn{
server: server,
remoteAddr: conn.RemoteAddr(),
ip: conn.RemoteAddr().String(),
gn: conn,
@ -44,8 +46,9 @@ func newGNetConn(conn gnet.Conn) *Conn {
}
// newKcpConn 创建一个处理WebSocket的连接
func newWebsocketConn(ws *websocket.Conn, ip string) *Conn {
func newWebsocketConn(server *Server, ws *websocket.Conn, ip string) *Conn {
return &Conn{
server: server,
remoteAddr: ws.RemoteAddr(),
ip: ip,
ws: ws,
@ -58,6 +61,7 @@ func newWebsocketConn(ws *websocket.Conn, ip string) *Conn {
// Conn 服务器连接
type Conn struct {
server *Server
remoteAddr net.Addr
ip string
ws *websocket.Conn
@ -80,8 +84,17 @@ func (slf *Conn) GetIP() string {
}
// Write 向连接中写入数据
func (slf *Conn) Write(data []byte) error {
return slf.write(data)
// - messageType: websocket模式中指定消息类型
func (slf *Conn) Write(data []byte, messageType ...int) {
if slf.IsWebsocket() {
if len(messageType) > 0 {
slf.server.PushMessage(MessageTypeWritePacket, slf, data, messageType[0])
} else {
slf.server.PushMessage(MessageTypeWritePacket, slf, data, -1)
}
} else {
slf.server.PushMessage(MessageTypeWritePacket, slf, data)
}
}
// Close 关闭连接
@ -114,3 +127,8 @@ func (slf *Conn) ReleaseData() *Conn {
}
return slf
}
// IsWebsocket 是否是websocket连接
func (slf *Conn) IsWebsocket() bool {
return slf.server.network == NetworkWebsocket
}

View File

@ -17,4 +17,5 @@ var (
ErrPleaseUseWebsocketHandle = errors.New("in Websocket mode, please use the RegConnectionReceiveWebsocketPacketEvent function to register")
ErrPleaseUseOrdinaryPacketHandle = errors.New("non Websocket mode, please use the RegConnectionReceivePacketEvent function to register")
ErrOnlySupportSocket = errors.New("only supports Socket programming")
ErrWebsocketMessageTypeWritePacketAttrs = errors.New("MessageTypeWritePacket must contain *Conn and []byte or *Conn and []byte and MessageType(int)")
)

View File

@ -18,7 +18,7 @@ func (slf *gNet) OnShutdown(server gnet.Server) {
}
func (slf *gNet) OnOpened(c gnet.Conn) (out []byte, action gnet.Action) {
conn := newGNetConn(c)
conn := newGNetConn(slf.Server, c)
c.SetContext(conn)
slf.OnConnectionOpenedEvent(conn)
return

View File

@ -6,6 +6,11 @@ const (
// - []byte
MessageTypePacket MessageType = iota
// MessageTypeWritePacket 数据包消息类型:该类型的消息将对客户端进行写入
// - *server.Conn
// - []byte
MessageTypeWritePacket
// MessageTypeError 错误消息类型:根据不同的错误状态,将交由 Server 进行统一处理
// - error
// - server.MessageErrorAction
@ -79,6 +84,38 @@ func (slf MessageType) deconstructPacket(attrs ...any) (conn *Conn, packet []byt
return
}
func (slf MessageType) deconstructWebSocketWritePacket(attrs ...any) (conn *Conn, packet []byte, messageType int) {
messageType = -1
if len(attrs) != 3 {
panic(ErrWebsocketMessageTypeWritePacketAttrs)
}
var ok bool
if conn, ok = attrs[0].(*Conn); !ok {
panic(ErrWebsocketMessageTypeWritePacketAttrs)
}
if packet, ok = attrs[1].([]byte); !ok {
panic(ErrWebsocketMessageTypeWritePacketAttrs)
}
if messageType, ok = attrs[2].(int); !ok {
panic(ErrWebsocketMessageTypeWritePacketAttrs)
}
return
}
func (slf MessageType) deconstructWritePacket(attrs ...any) (conn *Conn, packet []byte) {
if len(attrs) != 2 {
panic(ErrMessageTypePacketAttrs)
}
var ok bool
if conn, ok = attrs[0].(*Conn); !ok {
panic(ErrMessageTypePacketAttrs)
}
if packet, ok = attrs[1].([]byte); !ok {
panic(ErrMessageTypePacketAttrs)
}
return
}
func (slf MessageType) deconstructError(attrs ...any) (err error, action MessageErrorAction) {
if len(attrs) != 2 {
panic(ErrMessageTypeErrorAttrs)

View File

@ -70,6 +70,19 @@ func WithProd() Option {
}
}
// WithWebsocketWriteMessageType 设置客户端写入的Websocket消息类型
// - 默认: WebsocketMessageTypeBinary
func WithWebsocketWriteMessageType(messageType int) Option {
return func(srv *Server) {
switch messageType {
case WebsocketMessageTypeText, WebsocketMessageTypeBinary, WebsocketMessageTypeClose, WebsocketMessageTypePing, WebsocketMessageTypePong:
srv.websocketWriteMessageType = messageType
default:
log.Warn("WithWebsocketWriteMessageType", zap.Int("MessageType", messageType), zap.Error(ErrWebsocketMessageTypeException))
}
}
}
// WithWebsocketMessageType 设置仅支持特定类型的Websocket消息
func WithWebsocketMessageType(messageTypes ...int) Option {
return func(srv *Server) {

View File

@ -32,6 +32,7 @@ func New(network Network, options ...Option) *Server {
options: options,
core: 1,
closeChannel: make(chan struct{}),
websocketWriteMessageType: WebsocketMessageTypeBinary,
}
server.event.Server = server
@ -73,6 +74,7 @@ type Server struct {
core int // 消息处理核心数
diversionMessageChannels []chan *message // 分流消息管道
diversionConsistency *hash.Consistency // 哈希一致性分流器
websocketWriteMessageType int // websocket写入的消息类型
}
// Run 使用特定地址运行服务器
@ -165,7 +167,7 @@ func (slf *Server) Run(addr string) error {
continue
}
conn := newKcpConn(session)
conn := newKcpConn(slf, session)
slf.OnConnectionOpenedEvent(conn)
go func(conn *Conn) {
@ -236,7 +238,7 @@ func (slf *Server) Run(addr string) error {
}
}
conn := newWebsocketConn(ws, ip)
conn := newWebsocketConn(slf, ws, ip)
for k, v := range request.URL.Query() {
if len(v) == 1 {
conn.SetData(k, v)
@ -403,14 +405,32 @@ func (slf *Server) dispatchMessage(msg *message) {
case MessageTypePacket:
if slf.network == NetworkWebsocket {
conn, packet, messageType := msg.t.deconstructWebSocketPacket(msg.attrs...)
if slf.diversionConsistency != nil {
slf.diversionConsistency.PickNode(conn)
}
slf.OnConnectionReceiveWebsocketPacketEvent(conn, packet, messageType)
} else {
conn, packet := msg.t.deconstructPacket(msg.attrs...)
slf.OnConnectionReceivePacketEvent(conn, packet)
}
case MessageTypeWritePacket:
if slf.network == NetworkWebsocket {
conn, packet, messageType := msg.t.deconstructWebSocketWritePacket(msg.attrs...)
if messageType == -1 {
messageType = slf.websocketWriteMessageType
}
if err := conn.ws.WriteMessage(messageType, packet); err != nil {
log.Debug("Server", zap.String("ConnID", conn.GetID()), zap.Error(err))
}
} else {
var err error
conn, packet := msg.t.deconstructPacket(msg.attrs...)
if conn.gn != nil {
err = conn.gn.AsyncWrite(packet)
} else if conn.kcp != nil {
_, err = conn.kcp.Write(packet)
}
if err != nil {
log.Debug("Server", zap.String("ConnID", conn.GetID()), zap.Error(err))
}
}
case MessageTypeError:
err, action := msg.t.deconstructError(msg.attrs...)
switch action {