Try to handle tcp fragmentation

This commit is contained in:
bdnugget 2025-01-15 10:51:43 +01:00
parent a48fef0186
commit 23474c19dc

59
main.go
View File

@ -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
}