Search code examples
gotcptcpclient

How I can receive data for ever from TCP server


I try to create TCP client to receive data from TCP server, but after server sending data only I receive data one even if server send many data, and I want to receive data forever, and I don't know what is my problem,and

Client:

func main() {
    tcpAddr := "localhost:3333"
    conn, err := net.DialTimeout("tcp", tcpAddr, time.Second*7)
    if err != nil {
        log.Println(err)
    }
    defer conn.Close()
    // conn.Write([]byte("Hello World"))

    connBuf := bufio.NewReader(conn)
    for {
        bytes, err := connBuf.ReadBytes('\n')
        if err != nil {
            log.Println("Rrecv Error:", err)
        }

        if len(bytes) > 0 {
            fmt.Println(string(bytes))
        }
        time.Sleep(time.Second * 2)
    }
}

I'm following this example to create TCP test server

Server:

// Handles incoming requests.
func handleRequest(conn net.Conn) {
    // Make a buffer to hold incoming data.
    buf := make([]byte, 1024)
    // Read the incoming connection into the buffer.
    _, err := conn.Read(buf)
    if err != nil {
        fmt.Println("Error reading:", err.Error())
    }
    fmt.Println(buf)
    // Send a response back to person contacting us.
    var msg string
    fmt.Scanln(&msg)
    conn.Write([]byte(msg))
    // Close the connection when you're done with it.
    conn.Close()
}

Solution

  • Read requires a Write on the other side of the connection

    want to receive data forever

    Then you have to send data forever. There's a for loop on the receiving end, but no looping on the sending end. The server writes its message once and closes the connection.

    Server expects to get msg from client but client doesn't send it

        // conn.Write([]byte("Hello World"))
    

    That's supposed to provide the msg value to the server

        _, err := conn.Read(buf)
    

    So those two lines don't match.

    Client expects a newline but server isn't sending one

    fmt.Scanln expects to put each whitespace separated value into the corresponding argument. It does not capture the whitespace. So:

    1. Only up to the first whitespace of what you type into server's stdin will be stored in msg
    2. Newline will not be stored in msg.

    But your client is doing

            bytes, err := connBuf.ReadBytes('\n')
    

    The \n never comes. The client never gets done reading that first msg.

    bufio.NewScanner would be a better way to collect data from stdin, since you're likely to want to capture whitespace as well. Don't forget to append the newline to each line of text you send, because the client expects it!

    Working code

    I put these changes together into a working example on the playground. To get it working in that context, I had to make a few other changes too.

    • Running server and client in the same process
    • Hard coded 3 clients so the program ended in limited amount of time
    • Hard coded 10 receives in the client so program can end
    • Hard coded 3 server connections handled so program can end
    • Removed fmt.Scanln and have server just return the original message sent (because playground provides no stdin mechanism)

    Should be enough to get you started.