From 23474c19dc152d730bb554040a92d0b5a8ec59e9 Mon Sep 17 00:00:00 2001 From: bdnugget Date: Wed, 15 Jan 2025 10:51:43 +0100 Subject: [PATCH] Try to handle tcp fragmentation --- main.go | 59 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/main.go b/main.go index 1159913..bb4ce58 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,10 @@ package main import ( + "bufio" + "encoding/binary" "fmt" + "io" "log" "net" "sync" @@ -76,22 +79,29 @@ func handleConnection(conn net.Conn) { PlayerId: int32(playerID), CurrentTick: 0, } - data, err := proto.Marshal(serverMsg) - if err != nil { - log.Printf("Failed to marshal ServerMessage for player %d: %v", playerID, err) - return - } - if _, err := conn.Write(data); err != nil { + if err := writeMessage(conn, serverMsg); err != nil { log.Printf("Failed to send player ID to player %d: %v", playerID, err) return } // Listen for incoming actions from this player - buf := make([]byte, 4096) + reader := bufio.NewReader(conn) for { - n, err := conn.Read(buf) - if err != nil { - log.Printf("Error reading from player %d: %v", playerID, err) + // Read message length + lengthBuf := make([]byte, 4) + if _, err := io.ReadFull(reader, lengthBuf); err != nil { + log.Printf("Error reading message length from player %d: %v", playerID, err) + delete(players, playerID) + delete(playerConns, playerID) + delete(actionQueue, playerID) + return + } + messageLength := binary.BigEndian.Uint32(lengthBuf) + + // Read message body + messageBuf := make([]byte, messageLength) + if _, err := io.ReadFull(reader, messageBuf); err != nil { + log.Printf("Error reading message from player %d: %v", playerID, err) delete(players, playerID) delete(playerConns, playerID) delete(actionQueue, playerID) @@ -99,7 +109,7 @@ func handleConnection(conn net.Conn) { } batch := &pb.ActionBatch{} - if err := proto.Unmarshal(buf[:n], batch); err != nil { + if err := proto.Unmarshal(messageBuf, batch); err != nil { log.Printf("Failed to unmarshal action batch for player %d: %v", playerID, err) continue } @@ -173,16 +183,29 @@ func processActions() { state.ChatMessages = chatHistory[max(0, len(chatHistory)-5):] // Only send last 5 messages chatMutex.RUnlock() - data, err := proto.Marshal(state) - if err != nil { - log.Printf("Failed to marshal game state: %v", err) - return - } - // Send to each connected player for _, conn := range playerConns { - if _, err := conn.Write(data); err != nil { + if err := writeMessage(conn, state); err != nil { log.Printf("Failed to send update: %v", err) } } } + +// Helper function to write length-prefixed messages +func writeMessage(conn net.Conn, msg proto.Message) error { + data, err := proto.Marshal(msg) + if err != nil { + return err + } + + // Write length prefix + lengthBuf := make([]byte, 4) + binary.BigEndian.PutUint32(lengthBuf, uint32(len(data))) + if _, err := conn.Write(lengthBuf); err != nil { + return err + } + + // Write message body + _, err = conn.Write(data) + return err +}