Can't run the go routines while building chat app with golang

Viewed 22

I'm trying to build a chat app with golang. However, I've encountered a problem that if I wrap the code of the for loop into a Sender() function and using goroutines, the client will shut down immediately. But if I put it in the main function, it can run correctly.

Here is the client code.

package main

import (
    "fmt"
    "net"
    "os"
    "os/signal"
    "syscall"
)

const (
    SERVER_HOST = "localhost"
    SERVER_PORT = "9988"
    SERVER_TYPE = "tcp"
)

var connection net.Conn
var err error

func main() {
    SetupCloseHandler()
    //establish connection
    connection, err = net.Dial(SERVER_TYPE, SERVER_HOST+":"+SERVER_PORT)
    if err != nil {
        panic(err)
    }
    //receive some data
    go Receiver()
    // go Sender()
    for {
        var input string
        fmt.Print("Enter text: ")
        fmt.Scan(&input)
        _, err = connection.Write([]byte(input))
        if err != nil {
            panic(err)
        }
    }
}

// func Sender() {
//  for {
//      var input string
//      fmt.Print("Enter text: ")
//      fmt.Scan(&input)
//      _, err = connection.Write([]byte(input))
//      if err != nil {
//          panic(err)
//      }
//  }
// }

func Receiver() {
    for {
        buffer := make([]byte, 1024)
        mLen, err := connection.Read(buffer)
        if err != nil {
            panic(err)
        }
        fmt.Println("Received: ", string(buffer[:mLen]))
    }
}

func SetupCloseHandler() {
    c := make(chan os.Signal, 2)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM)
    go func() {
        <-c
        fmt.Println("\r- Ctrl+C pressed in Terminal")
        os.Exit(0)
    }()
}

Here is the server code.

package main

import (
    "fmt"
    "net"
    "os"

    "github.com/google/uuid"
)

const (
    SERVER_HOST = "localhost"
    SERVER_PORT = "9988"
    SERVER_TYPE = "tcp"
)

var clientMap = make(map[string]net.Conn)

func main() {
    fmt.Println("Server Running...")
    server, err := net.Listen(SERVER_TYPE, SERVER_HOST+":"+SERVER_PORT)
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        os.Exit(1)
    }
    defer server.Close()

    fmt.Println("Listening on " + SERVER_HOST + ":" + SERVER_PORT)
    fmt.Println("Waiting for client...")
    for {
        connection, err := server.Accept()
        id := uuid.New().String()
        clientMap[id] = connection
        if err != nil {
            fmt.Println("Error accepting: ", err.Error())
            os.Exit(1)
        }
        fmt.Printf("client %s connected\n", id)
        go processClient(connection, id)
    }
}
func processClient(connection net.Conn, id string) {
    defer connection.Close()
    for {
        buffer := make([]byte, 1024)
        mLen, err := connection.Read(buffer)
        if err != nil {
            fmt.Println("Error reading:", err.Error())
            delete(clientMap, id)
            connection.Close()
            return
        }
        fmt.Println("Received: ", string(buffer[:mLen]))
        for k, c := range clientMap {
            if k != id {
                c.Write(buffer[:mLen])
            }
        }
    }
}

0 Answers
Related