优化连接
This commit is contained in:
parent
dae2982090
commit
41b0417338
|
@ -1 +0,0 @@
|
|||
简单游戏实现demo
|
|
@ -1,23 +0,0 @@
|
|||
package game
|
||||
|
||||
import (
|
||||
"minotaur/game"
|
||||
"minotaur/game/builtin"
|
||||
"minotaur/server"
|
||||
)
|
||||
|
||||
var (
|
||||
Server *server.Server
|
||||
Game *app
|
||||
)
|
||||
|
||||
func init() {
|
||||
Server = server.New(server.NetworkWebsocket)
|
||||
Game = &app{
|
||||
World: builtin.NewWorld[int64, *Player](0),
|
||||
}
|
||||
}
|
||||
|
||||
type app struct {
|
||||
game.World[int64, *Player]
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package game
|
||||
|
||||
import (
|
||||
"log"
|
||||
"minotaur/game"
|
||||
"minotaur/game/builtin"
|
||||
"minotaur/server"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewPlayer(id int64, conn *server.Conn) *Player {
|
||||
player := &Player{
|
||||
Player: builtin.NewPlayer[int64](id, conn),
|
||||
}
|
||||
gameplay := builtin.NewGameplay()
|
||||
gameplayOver := builtin.NewGameplayOver()
|
||||
gameplayTime := builtin.NewGameplayTime(gameplay, gameplayOver)
|
||||
|
||||
player.GameplayTime = gameplayTime
|
||||
|
||||
return player
|
||||
}
|
||||
|
||||
type Player struct {
|
||||
*builtin.Player[int64]
|
||||
game.GameplayTime
|
||||
}
|
||||
|
||||
func (slf *Player) Start() {
|
||||
_ = slf.GameStart(func() error {
|
||||
log.Println("game start, init map...")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (slf *Player) onGameplayStart(t time.Time) {
|
||||
slf.SetEndTime(t.Add(60 * time.Second))
|
||||
log.Println("the game will end in 60 seconds")
|
||||
}
|
||||
|
||||
func (slf *Player) onGameplayOver() {
|
||||
log.Println("game over")
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package game
|
||||
|
||||
import (
|
||||
"minotaur/game"
|
||||
"minotaur/server"
|
||||
"minotaur/utils/sole"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Server.RegConnectionOpenedEvent(onConnectionOpened)
|
||||
Game.RegPlayerLeaveWorldEvent(onConnectionClosed)
|
||||
Server.RegConnectionReceivePacketEvent(onConnectionReceivePacket)
|
||||
}
|
||||
|
||||
func onConnectionReceivePacket(srv *server.Server, conn *server.Conn, packet []byte) {
|
||||
player := Game.World.GetPlayerWithConnID(conn.GetID())
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
|
||||
player.RegGameplayStartEvent(player.onGameplayStart)
|
||||
player.RegGameplayOverEvent(player.onGameplayOver)
|
||||
|
||||
switch string(packet) {
|
||||
case "start":
|
||||
player.Start()
|
||||
}
|
||||
}
|
||||
|
||||
func onConnectionClosed(world game.World[int64, *Player], player *Player) {
|
||||
Game.Leave(player.GetID())
|
||||
player.Close()
|
||||
}
|
||||
|
||||
func onConnectionOpened(srv *server.Server, conn *server.Conn) {
|
||||
player := NewPlayer(sole.GetSync(), conn)
|
||||
if err := Game.World.Join(player); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package main
|
||||
|
||||
import "minotaur/game/builtin/examples/game/game"
|
||||
|
||||
func main() {
|
||||
if err := game.Server.Run(":9999"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"minotaur/game"
|
||||
"minotaur/game/builtin"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewGame() *Game {
|
||||
gameplay := builtin.NewGameplay()
|
||||
gameplayOver := builtin.NewGameplayOver()
|
||||
return &Game{
|
||||
GameplayTime: builtin.NewGameplayTime(gameplay, gameplayOver),
|
||||
}
|
||||
}
|
||||
|
||||
type Game struct {
|
||||
game.GameplayTime
|
||||
wait sync.WaitGroup
|
||||
}
|
||||
|
||||
func (slf *Game) init() error {
|
||||
slf.wait.Add(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (slf *Game) onGameStart(startTime time.Time) {
|
||||
log.Println("游戏开始")
|
||||
slf.SetEndTime(startTime.Add(3 * time.Second))
|
||||
}
|
||||
|
||||
func (slf *Game) onGameOver() {
|
||||
log.Println("游戏结束")
|
||||
slf.wait.Done()
|
||||
}
|
||||
|
||||
func main() {
|
||||
g := NewGame()
|
||||
g.RegGameplayStartEvent(g.onGameStart)
|
||||
g.RegGameplayOverEvent(g.onGameOver)
|
||||
|
||||
if err := g.GameStart(g.init); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
g.wait.Wait()
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
conn, err := net.Dial("tcp", "server.natappfree.cc:37775")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
defer conn.Close() // 关闭TCP连接
|
||||
inputReader := bufio.NewReader(os.Stdin)
|
||||
go func() {
|
||||
for {
|
||||
buf := [512]byte{}
|
||||
n, err := conn.Read(buf[:])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
fmt.Println(string(buf[:n]))
|
||||
}
|
||||
}()
|
||||
for {
|
||||
input, _ := inputReader.ReadString('\n') // 读取用户输入
|
||||
inputInfo := strings.Trim(input, "\r\n")
|
||||
if strings.ToUpper(inputInfo) == "Q" { // 如果输入q就退出
|
||||
return
|
||||
}
|
||||
_, err := conn.Write([]byte(inputInfo)) // 发送数据
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"minotaur/server"
|
||||
"minotaur/utils/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
srv := server.New(server.NetworkTCP)
|
||||
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
|
||||
srv.GetConnections().RangeSkip(func(id string, c *server.Conn) bool {
|
||||
if id == conn.GetID() {
|
||||
return false
|
||||
}
|
||||
|
||||
if err := c.Write([]byte(fmt.Sprintf("[%s]: %s", conn.GetID(), string(packet)))); err != nil {
|
||||
log.Debug("Message", zap.Error(err))
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
if err := srv.Run(":8888"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -19,10 +19,6 @@ func (slf *Player[ID]) GetID() ID {
|
|||
return slf.id
|
||||
}
|
||||
|
||||
func (slf *Player[ID]) GetConnID() string {
|
||||
return slf.conn.GetID()
|
||||
}
|
||||
|
||||
// Send 向该玩家发送数据
|
||||
func (slf *Player[ID]) Send(packet []byte) error {
|
||||
return slf.conn.Write(packet)
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
func NewRoom[PlayerID comparable, Player game.Player[PlayerID]](guid int64) *Room[PlayerID, Player] {
|
||||
return &Room[PlayerID, Player]{
|
||||
guid: guid,
|
||||
playersConn: synchronization.NewMap[string, Player](),
|
||||
players: synchronization.NewMap[PlayerID, Player](),
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +19,6 @@ type Room[PlayerID comparable, Player game.Player[PlayerID]] struct {
|
|||
owner PlayerID
|
||||
noMaster bool
|
||||
playerLimit int
|
||||
playersConn *synchronization.Map[string, Player]
|
||||
players *synchronization.Map[PlayerID, Player]
|
||||
kickCheckHandle func(id, target PlayerID) error
|
||||
|
||||
|
@ -37,10 +35,6 @@ func (slf *Room[PlayerID, Player]) GetPlayerLimit() int {
|
|||
return slf.playerLimit
|
||||
}
|
||||
|
||||
func (slf *Room[PlayerID, Player]) GetPlayerWithConnID(id string) Player {
|
||||
return slf.playersConn.Get(id)
|
||||
}
|
||||
|
||||
func (slf *Room[PlayerID, Player]) GetPlayer(id PlayerID) Player {
|
||||
return slf.players.Get(id)
|
||||
}
|
||||
|
@ -68,9 +62,8 @@ func (slf *Room[PlayerID, Player]) Join(player Player) error {
|
|||
if slf.players.Size() >= slf.playerLimit && slf.playerLimit > 0 {
|
||||
return ErrWorldPlayerLimit
|
||||
}
|
||||
log.Debug("Room.Join", zap.Any("guid", slf.GetGuid()), zap.Any("player", player.GetID()), zap.String("conn", player.GetConnID()))
|
||||
log.Debug("Room.Join", zap.Any("guid", slf.GetGuid()), zap.Any("player", player.GetID()))
|
||||
slf.players.Set(player.GetID(), player)
|
||||
slf.playersConn.Set(player.GetConnID(), player)
|
||||
if slf.players.Size() == 1 && !slf.noMaster {
|
||||
slf.owner = player.GetID()
|
||||
}
|
||||
|
@ -83,10 +76,9 @@ func (slf *Room[PlayerID, Player]) Leave(id PlayerID) {
|
|||
if !exist {
|
||||
return
|
||||
}
|
||||
log.Debug("Room.Leave", zap.Any("guid", slf.GetGuid()), zap.Any("player", player.GetID()), zap.String("conn", player.GetConnID()))
|
||||
log.Debug("Room.Leave", zap.Any("guid", slf.GetGuid()), zap.Any("player", player.GetID()))
|
||||
slf.OnPlayerLeaveRoomEvent(player)
|
||||
slf.players.Delete(player.GetID())
|
||||
slf.playersConn.Delete(player.GetConnID())
|
||||
}
|
||||
|
||||
func (slf *Room[PlayerID, Player]) KickOut(id, target PlayerID, reason string) error {
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
func NewWorld[PlayerID comparable, Player game.Player[PlayerID]](guid int64, options ...WorldOption[PlayerID, Player]) *World[PlayerID, Player] {
|
||||
world := &World[PlayerID, Player]{
|
||||
guid: guid,
|
||||
playersConn: synchronization.NewMap[string, Player](),
|
||||
players: synchronization.NewMap[PlayerID, Player](),
|
||||
playerActors: synchronization.NewMap[PlayerID, *synchronization.Map[int64, game.Actor]](),
|
||||
owners: synchronization.NewMap[int64, PlayerID](),
|
||||
|
@ -29,7 +28,6 @@ type World[PlayerID comparable, Player game.Player[PlayerID]] struct {
|
|||
guid int64
|
||||
actorGuid atomic.Int64
|
||||
playerLimit int
|
||||
playersConn *synchronization.Map[string, Player]
|
||||
players *synchronization.Map[PlayerID, Player]
|
||||
playerActors *synchronization.Map[PlayerID, *synchronization.Map[int64, game.Actor]]
|
||||
owners *synchronization.Map[int64, PlayerID]
|
||||
|
@ -54,10 +52,6 @@ func (slf *World[PlayerID, Player]) GetPlayerLimit() int {
|
|||
return slf.playerLimit
|
||||
}
|
||||
|
||||
func (slf *World[PlayerID, Player]) GetPlayerWithConnID(id string) Player {
|
||||
return slf.playersConn.Get(id)
|
||||
}
|
||||
|
||||
func (slf *World[PlayerID, Player]) GetPlayer(id PlayerID) Player {
|
||||
return slf.players.Get(id)
|
||||
}
|
||||
|
@ -108,13 +102,12 @@ func (slf *World[PlayerID, Player]) Join(player Player) error {
|
|||
if slf.players.Size() >= slf.playerLimit && slf.playerLimit > 0 {
|
||||
return ErrWorldPlayerLimit
|
||||
}
|
||||
log.Debug("World.Join", zap.Int64("guid", slf.GetGuid()), zap.Any("player", player.GetID()), zap.String("conn", player.GetConnID()))
|
||||
log.Debug("World.Join", zap.Int64("guid", slf.GetGuid()), zap.Any("player", player.GetID()))
|
||||
slf.players.Set(player.GetID(), player)
|
||||
if actors := slf.playerActors.Get(player.GetID()); actors == nil {
|
||||
actors = synchronization.NewMap[int64, game.Actor]()
|
||||
slf.playerActors.Set(player.GetID(), actors)
|
||||
}
|
||||
slf.playersConn.Set(player.GetConnID(), player)
|
||||
slf.OnPlayerJoinWorldEvent(player)
|
||||
return nil
|
||||
}
|
||||
|
@ -124,7 +117,7 @@ func (slf *World[PlayerID, Player]) Leave(id PlayerID) {
|
|||
if !exist {
|
||||
return
|
||||
}
|
||||
log.Debug("World.Leave", zap.Int64("guid", slf.GetGuid()), zap.Any("player", player.GetID()), zap.String("conn", player.GetConnID()))
|
||||
log.Debug("World.Leave", zap.Int64("guid", slf.GetGuid()), zap.Any("player", player.GetID()))
|
||||
slf.OnPlayerLeaveWorldEvent(player)
|
||||
slf.playerActors.Get(player.GetID()).Range(func(guid int64, actor game.Actor) {
|
||||
slf.OnActorAnnihilationEvent(actor)
|
||||
|
@ -132,7 +125,6 @@ func (slf *World[PlayerID, Player]) Leave(id PlayerID) {
|
|||
})
|
||||
slf.playerActors.Delete(player.GetID())
|
||||
slf.players.Delete(player.GetID())
|
||||
slf.playersConn.Delete(player.GetConnID())
|
||||
}
|
||||
|
||||
func (slf *World[PlayerID, Player]) AddActor(actor game.Actor) {
|
||||
|
@ -186,7 +178,6 @@ func (slf *World[PlayerID, Player]) Reset() {
|
|||
slf.owners.Clear()
|
||||
slf.actors.Clear()
|
||||
slf.actorGuid.Store(0)
|
||||
slf.playersConn.Clear()
|
||||
slf.OnWorldResetEvent()
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@ package game
|
|||
type Player[ID comparable] interface {
|
||||
// GetID 用户玩家ID
|
||||
GetID() ID
|
||||
// GetConnID 获取连接ID
|
||||
GetConnID() string
|
||||
// Send 发送数据包
|
||||
Send(packet []byte) error
|
||||
// Close 关闭玩家并且释放其资源
|
||||
|
|
|
@ -8,8 +8,6 @@ type Room[PlayerID comparable, P Player[PlayerID]] interface {
|
|||
GetGuid() int64
|
||||
// GetPlayerLimit 获取玩家人数上限
|
||||
GetPlayerLimit() int
|
||||
// GetPlayerWithConnID 根据连接ID获取玩家
|
||||
GetPlayerWithConnID(id string) P
|
||||
// GetPlayer 根据玩家id获取玩家
|
||||
GetPlayer(id PlayerID) P
|
||||
// GetPlayers 获取房间中的所有玩家
|
||||
|
|
|
@ -8,8 +8,6 @@ type World[PlayerID comparable, P Player[PlayerID]] interface {
|
|||
GetGuid() int64
|
||||
// GetPlayerLimit 获取玩家人数上限
|
||||
GetPlayerLimit() int
|
||||
// GetPlayerWithConnID 根据连接ID获取玩家
|
||||
GetPlayerWithConnID(id string) P
|
||||
// GetPlayer 根据玩家id获取玩家
|
||||
GetPlayer(id PlayerID) P
|
||||
// GetPlayers 获取世界中的所有玩家
|
||||
|
|
|
@ -30,9 +30,9 @@ func newGNetConn(conn gnet.Conn) *Conn {
|
|||
}
|
||||
|
||||
// newKcpConn 创建一个处理WebSocket的连接
|
||||
func newWebsocketConn(ws *websocket.Conn) *Conn {
|
||||
func newWebsocketConn(ws *websocket.Conn, ip string) *Conn {
|
||||
return &Conn{
|
||||
ip: ws.RemoteAddr().String(),
|
||||
ip: ip,
|
||||
ws: ws,
|
||||
write: func(data []byte) error {
|
||||
return ws.WriteMessage(websocket.BinaryMessage, data)
|
||||
|
|
|
@ -57,7 +57,6 @@ func (slf *event) RegConnectionClosedEvent(handle ConnectionClosedEventHandle) {
|
|||
|
||||
func (slf *event) OnConnectionClosedEvent(conn *Conn) {
|
||||
log.Debug("Server", zap.String("ConnectionClosed", conn.GetID()))
|
||||
slf.Server.connections.Delete(conn.ip)
|
||||
for _, handle := range slf.connectionClosedEventHandles {
|
||||
handle(slf.Server, conn)
|
||||
}
|
||||
|
@ -74,7 +73,6 @@ func (slf *event) RegConnectionOpenedEvent(handle ConnectionOpenedEventHandle) {
|
|||
|
||||
func (slf *event) OnConnectionOpenedEvent(conn *Conn) {
|
||||
log.Debug("Server", zap.String("ConnectionOpened", conn.GetID()))
|
||||
slf.Server.connections.Set(conn.ip, conn)
|
||||
for _, handle := range slf.connectionOpenedEventHandles {
|
||||
handle(slf.Server, conn)
|
||||
}
|
||||
|
|
|
@ -2,36 +2,29 @@ package server
|
|||
|
||||
import (
|
||||
"github.com/panjf2000/gnet"
|
||||
"minotaur/utils/synchronization"
|
||||
"time"
|
||||
)
|
||||
|
||||
type gNet struct {
|
||||
*Server
|
||||
connections *synchronization.Map[string, *Conn]
|
||||
}
|
||||
|
||||
func (slf *gNet) OnInitComplete(server gnet.Server) (action gnet.Action) {
|
||||
slf.connections = synchronization.NewMap[string, *Conn]()
|
||||
return
|
||||
}
|
||||
|
||||
func (slf *gNet) OnShutdown(server gnet.Server) {
|
||||
for k := range slf.connections.Map() {
|
||||
slf.connections.Delete(k)
|
||||
}
|
||||
slf.connections = nil
|
||||
|
||||
}
|
||||
|
||||
func (slf *gNet) OnOpened(c gnet.Conn) (out []byte, action gnet.Action) {
|
||||
conn := newGNetConn(c)
|
||||
slf.connections.Set(c.RemoteAddr().String(), conn)
|
||||
slf.OnConnectionOpenedEvent(conn)
|
||||
return
|
||||
}
|
||||
|
||||
func (slf *gNet) OnClosed(c gnet.Conn, err error) (action gnet.Action) {
|
||||
slf.OnConnectionClosedEvent(slf.connections.DeleteGet(c.RemoteAddr().String()))
|
||||
slf.OnConnectionClosedEvent(newGNetConn(c))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -44,12 +37,8 @@ func (slf *gNet) AfterWrite(c gnet.Conn, b []byte) {
|
|||
}
|
||||
|
||||
func (slf *gNet) React(packet []byte, c gnet.Conn) (out []byte, action gnet.Action) {
|
||||
if conn, exist := slf.connections.GetExist(c.RemoteAddr().String()); exist {
|
||||
slf.Server.PushMessage(MessageTypePacket, conn, packet)
|
||||
slf.Server.PushMessage(MessageTypePacket, newGNetConn(c), packet)
|
||||
return nil, gnet.None
|
||||
} else {
|
||||
return nil, gnet.Close
|
||||
}
|
||||
}
|
||||
|
||||
func (slf *gNet) Tick() (delay time.Duration, action gnet.Action) {
|
||||
|
|
|
@ -54,7 +54,6 @@ type Server struct {
|
|||
httpServer *http.Server // HTTP模式下的服务器
|
||||
grpcServer *grpc.Server // GRPC模式下的服务器
|
||||
|
||||
connections *synchronization.Map[string, *Conn] // 所有在线的连接
|
||||
gServer *gNet // TCP或UDP模式下的服务器
|
||||
messagePool *synchronization.Pool[*message] // 消息池
|
||||
messagePoolSize int // 消息池大小
|
||||
|
@ -85,7 +84,6 @@ func (slf *Server) Run(addr string) error {
|
|||
slf.addr = addr
|
||||
var protoAddr = fmt.Sprintf("%s://%s", slf.network, slf.addr)
|
||||
var connectionInitHandle = func(callback func()) {
|
||||
slf.connections = synchronization.NewMap[string, *Conn]()
|
||||
slf.initMessageChannel = true
|
||||
if slf.messagePoolSize <= 0 {
|
||||
slf.messagePoolSize = 1024
|
||||
|
@ -209,7 +207,7 @@ func (slf *Server) Run(addr string) error {
|
|||
}
|
||||
}
|
||||
|
||||
conn := newWebsocketConn(ws)
|
||||
conn := newWebsocketConn(ws, ip)
|
||||
slf.OnConnectionOpenedEvent(conn)
|
||||
|
||||
defer func() {
|
||||
|
@ -273,11 +271,6 @@ func (slf *Server) IsDev() bool {
|
|||
return !slf.prod
|
||||
}
|
||||
|
||||
// GetConnections 获取所有在线的连接
|
||||
func (slf *Server) GetConnections() synchronization.MapReadonly[string, *Conn] {
|
||||
return slf.connections
|
||||
}
|
||||
|
||||
// Shutdown 停止运行服务器
|
||||
func (slf *Server) Shutdown(err error) {
|
||||
if slf.initMessageChannel {
|
||||
|
@ -288,9 +281,6 @@ func (slf *Server) Shutdown(err error) {
|
|||
log.Error("Server", zap.Error(shutdownErr))
|
||||
}
|
||||
}
|
||||
slf.connections.Range(func(connId string, conn *Conn) {
|
||||
conn.Close()
|
||||
})
|
||||
close(slf.messageChannel)
|
||||
slf.messagePool.Close()
|
||||
slf.initMessageChannel = false
|
||||
|
|
Loading…
Reference in New Issue