HTTP server from TCP socket (in Go)

AjMyyra :

I'm trying to create a TCP socket in Go, bind it into a VRF interface and to establish a HTTP server in that specific interface. The VRF binding works correctly, but starting the HTTP server returns an error stating "accept tcp 127.0.0.1:80: accept: invalid argument". Am I right to assume, that the socket is somehow defective and I'm creating it wrong?

Below is the simplified version reproducing the problem. VRF part is commented out as it doesn't affect the actual problem, but I'm leaving it here as I'm trying to avoid people telling me to just use net.Listen instead of sockets. VRF needs to be binded into first before it can be used so net.Listen isn't unfortunately an option.

package main

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

func main() {
    fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
    if err != nil {
        fmt.Printf("Error creating socket: %v", err)
        os.Exit(1)
    }

    // if err = syscall.SetsockoptString(fd, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, "vrfiface"); err != nil {
    //  fmt.Printf("Error binding to vrf: %v", err)
    //  os.Exit(1)
    // }

    sockAddr := &syscall.SockaddrInet4{
        Port: 80,
        Addr: [4]byte{127, 0, 0, 1},
    }

    if err = syscall.Bind(fd, sockAddr); err != nil {
        fmt.Printf("Error binding to IP and port: %v", err)
        os.Exit(1)
    }

    file := os.NewFile(uintptr(fd), "socketfile")
    if file == nil {
        fmt.Println("Error creating file")
        os.Exit(1)
    }

    listener, err := net.FileListener(file)
    if err != nil {
        fmt.Printf("Error creating a listener: %v", err)
        os.Exit(1)
    }

    http.HandleFunc("/", TestServer)
    if err = http.Serve(listener, nil); err != nil {
        fmt.Printf("Error serving HTTP requests: %v", err)
    }
}

func TestServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Test, %s!", r.URL.Path[1:])
}

Any pointers on solving this would be appreciated. Thank you!

Steffen Ullrich :

As mentioned in a comment by C Han already: you need to listen. The sequence of creating a server is to create the socket, bind to the IP and port, call listen and then accept incoming connections. If you forget to listen then you'll get the error you see. Thus:

if err = syscall.Bind(fd, sockAddr); err != nil {
     ...
}

if err = syscall.Listen(fd, 10); err != nil {
    fmt.Printf("Error listening %v", err)
    os.Exit(1)
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=6477&siteId=1