Improved network code

This commit is contained in:
2024-01-15 17:08:26 +01:00
parent 9b47e374c7
commit b885d70625
17 changed files with 241 additions and 72 deletions

View File

@ -3,6 +3,8 @@ package core
import (
"fmt"
"net"
"sync"
"sync/atomic"
"time"
)
@ -12,15 +14,38 @@ type Handler func([]byte, *Client)
// Server represents a UDP server.
type Server struct {
socket *net.UDPConn
clients map[string]*Client
handlers [256]Handler
clients sync.Map
count atomic.Int64
}
// New creates a new server.
func New() *Server {
return &Server{
clients: make(map[string]*Client),
}
timeout := 3 * time.Second
interval := time.Second
server := &Server{}
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for range ticker.C {
now := time.Now()
server.clients.Range(func(key, value interface{}) bool {
item := value.(*Client)
if !item.lastPacket.IsZero() && now.After(item.lastPacket.Add(timeout)) {
server.clients.Delete(key)
server.count.Add(-1)
}
return true
})
}
}()
return server
}
// AddHandler adds the handler for the given byte code.
@ -28,8 +53,14 @@ func (s *Server) AddHandler(code byte, handler Handler) {
s.handlers[code] = handler
}
// SendTo sends the data to a client.
func (s *Server) SendTo(data []byte, client *Client) {
// Count returns the number of connected clients.
func (s *Server) Count() int {
return int(s.count.Load())
}
// Send sends the data prefixed with the byte code to the client.
func (s *Server) Send(code byte, data []byte, client *Client) {
data = append([]byte{code}, data...)
_, err := s.socket.WriteToUDP(data, client.address)
if err != nil {
@ -91,25 +122,26 @@ func (s *Server) handle(data []byte, addr *net.UDPAddr) {
handler := s.handlers[data[0]]
if handler == nil {
fmt.Println("Unknown packet type.")
fmt.Printf("No callback registered for packet type %d\n", data[0])
return
}
handler(data, c)
handler(data[1:], c)
}
// getClient either returns a new or existing client for the requested address.
func (s *Server) getClient(addr *net.UDPAddr) *Client {
c, exists := s.clients[addr.String()]
obj, exists := s.clients.Load(addr.String())
if exists {
return c
return obj.(*Client)
}
c = &Client{
client := &Client{
address: addr,
}
s.clients[addr.String()] = c
return c
s.clients.Store(addr.String(), client)
s.count.Add(1)
return client
}

13
server/login.go Normal file
View File

@ -0,0 +1,13 @@
package main
import (
"fmt"
"server/core"
"server/packet"
)
// login checks the account credentials and gives a network peer access to an account.
func login(data []byte, client *core.Client) {
fmt.Println("2 - login!")
server.Send(packet.LOGIN, nil, client)
}

View File

@ -2,16 +2,13 @@ package main
import (
"server/core"
"server/packet"
)
var server = core.New()
func main() {
server := core.New()
server.AddHandler(0, func(data []byte, client *core.Client) {
// count := data[1]
// fmt.Println(count)
server.SendTo(data, client)
})
server.AddHandler(packet.PING, ping)
server.AddHandler(packet.LOGIN, login)
server.Run(4242)
}

8
server/packet/types.go Normal file
View File

@ -0,0 +1,8 @@
package packet
const (
PING = 1
LOGIN = 2
LOGOUT = 3
MOVE = 10
)

14
server/ping.go Normal file
View File

@ -0,0 +1,14 @@
package main
import (
"fmt"
"server/core"
"server/packet"
)
// ping is used as a heartbeat and latency check.
func ping(data []byte, client *core.Client) {
fmt.Println("1 - ping!")
server.Send(packet.PING, data, client)
fmt.Println(server.Count(), "clients")
}