0

I have written a very simple TCP server, which reads a connections and responds back with HELLO WORLD.

import (
    "fmt"
    "log"
    "net"
)

func handleRequest(conn net.Conn) {

    buff := make([]byte, 10)

    _, err := conn.Read(buff)

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(buff))

    conn.Write([]byte("HELLO WORLD"))
    conn.Close()
}

func main() {
    ln, err := net.Listen("tcp", ":8080")
    fmt.Println("Listening on Port 8080")
    if err != nil {
        log.Fatal(err)
    }
    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Fatal(err)
        }
        go handleRequest(conn)
    }

}

What is the problem with this code? When I run curl http://localhost:8080, I get this output

curl: (56) Recv failure: Connection reset by peer
HELLO WORLD%
buff:=make([]byte,1024)

Now if I increase the buffer size, this code works fine and I do not get that error after running curl.

echo -n "Hello" | nc localhost 8080

If I run the above command it works without any issues.

I really don't understand the cause of this.

1
  • 1
    You're using an HTTP client with a non-HTTP server, so I would expect it to fail. Commented Jan 3, 2020 at 14:55

1 Answer 1

5

Curl sends a large-ish HTTP request. Try to print out (or log) what conn.Read got and you'll see it. Curl could be unhappy because it's not getting a proper HTTP response back.

conn.Read should not overflow the buffer anyway, it reads up to the buffer size.

On the other hand the pipe to nc just sends 5 bytes on the TCP socket.


Here's a sample TCP server that talks proper HTTP:

package main

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

// handleConnection handles a single connected client.
func handleConnection(c net.Conn) {
    defer c.Close()

    scanner := bufio.NewScanner(c)
    // Scan first line for the request
    if !scanner.Scan() {
        log.Fatal(scanner.Err())
    }
    req := scanner.Text()
    for scanner.Scan() {
        // Scan until an empty line is seen
        if len(scanner.Text()) == 0 {
            break
        }
    }
    fmt.Println("req:", req)
    if strings.HasPrefix(req, "GET") {
        rt := fmt.Sprintf("HTTP/1.1 200 Success\r\n")
        rt += fmt.Sprintf("Connection: Close\r\n")
        rt += fmt.Sprintf("Content-Type: text/html\r\n\r\n")
        rt += fmt.Sprintf("<html><body>Nothing here</body></html>\r\n")
        c.Write([]byte(rt))
    } else {
        rt := fmt.Sprintf("HTTP/1.1 %v Error Occurred\r\n\r\n", 501)
        c.Write([]byte(rt))
    }
}

func main() {
    l, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal(err)
    }
    defer l.Close()
    for {
        // Wait for a connection.
        conn, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }
        go handleConnection(conn)
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Yes, curl actually prints some large header information, but if the buffer overflows shouldn't the read method return an error, it returns me the number of bytes processed. Also what if I don't know how big the incoming data is? How can I read that if I declare a fixed sized buffer. And curl Is getting back a response, I can see HELLO WORLD printed.
@Shubhangb: the buffer doesn't overflow in Go. Read fills up the buffer and returns how many bytes were actually read. If the data is longer than the buffer and the buffer is of size N, it will read N bytes and return N. If you don't want to guess the maximal buffer size you could use bytes.Buffer with something like io.Copy. See stackoverflow.com/a/24818043/8206 for example
I have understood the buffer part, regarding the error is it specific to curl?
@Shubhangb: curl expects to talk HTTP. Your server doesn't talk HTTP, but just writes "HELLO WORLD" back. This is not a valid HTTP response in itself, so curl is unhappy. I'm updating my answer to show a sample of a socket server that returns proper HTTP responses. Try this one with curl - it will work fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.