Search code examples
gotcpserver

Golang Bufio writer not writing to TCP connection


I'm working on a small server written in Golang. I'm looking at the following example:

https://gist.github.com/kenshinx/5796276

When trying to implement the Reader and Writer from the Bufio package, it's only possible to read from the connection. It looks like it's not writing anything (well, I'm not receiving anything client-side), and it's also not giving an error. Using the actual connection to write, instead of the bufio.Writer, works fine however.

Here's the code.

package main

import (
    "fmt"
    "net"
    "os"
    "bufio"
    "strings"
)

const (
    CONN_HOST = "localhost"
    CONN_TYPE = "tcp"
    CONN_PORT = "3333"
)

type Client struct{
    name string
    reader *bufio.Reader
    writer *bufio.Writer
    connection net.Conn
}

type Clients [] Client

var lobby Clients

func main() {
    c, err := net.Listen(CONN_TYPE, CONN_HOST+":"+CONN_PORT)

    if err != nil {
        fmt.Println("Error listening:", err.Error())
        os.Exit(1)
    }

    defer c.Close()
    fmt.Println("Server listening on port " + CONN_PORT)

    go matchmaking()

    for {
        conn, err := c.Accept()
        if err != nil {
            fmt.Println("Error accepting: ", err.Error())
            os.Exit(1)
        }

        if conn != nil {
            go handleRequest(conn)
        }
    }
}

func handleRequest(conn net.Conn) {
    client := &Client{
        reader: bufio.NewReader(conn),
        writer: bufio.NewWriter(conn),
        connection:conn,
    }

    client.name, _ = client.reader.ReadString('\n') // Works fine
    client.name = strings.TrimSpace(client.name)

    lobby = append(lobby, *client)
    fmt.Println("Client connected: " + client.name)
}

func matchmaking(){
    fmt.Println("Matchmaker started!")
    for {
        for i := range lobby {
            if len(lobby) >= 2 {
                go startMatch(lobby[i], lobby[i+1] )
                lobby = append(lobby[:i], lobby[i+1:]...) // Remove from lobby
                lobby = append(lobby[:i], lobby[i+1:]...)
            }
        }
    }
}

func startMatch(client1 Client, client2 Client){
    client1.writer.WriteString("found\n") // Doens't work?
    client2.writer.WriteString("found\n") // Doens't work?

    //client1.writer.Write([]byte("found\n")) => Doensn't work either
    //client1.connection.Write([]byte("found\n")) => this works fine..?

    fmt.Println("Starting match with: " + client1.name + " and " + client2.name)
    fmt.Println("Current lobby size is: ", len(lobby))
}

So as the title says suggests, why is the bufio.Writer not writing to connected clients?


Solution

  • The buffered writer has buffered the data. To push it further call writer.Flush.

    func startMatch(client1 Client, client2 Client){
        _, err := client1.writer.WriteString("found\n")
        // handle error here
        err = client1.writer.Flush()
        // handle error here
        _, err = client2.writer.WriteString("found\n")
        // handle error here
        err = client2.writer.Flush()
        // handle error here
    
        fmt.Println("Starting match with: " + client1.name + " and " + client2.name)
        fmt.Println("Current lobby size is: ", len(lobby))
    }
    

    It becomes important to handle errors also in flush operations as the underlying writer errors can bubble up at this point.