通过原始TCP套接字接受和路由HTTP请求

时间:2020-01-03 16:58:46

标签: http go tcp server

我正在构建一个Web服务器,该服务器必须接受来自客户端的HTTP请求,但还必须接受来自对等方的原始TCP套接字上的请求。由于HTTP运行在TCP之上,因此我试图通过TCP服务器路由HTTP请求,而不是运行两个单独的服务。

是否有一种简单的方法可以通过net.Conn.Read()读取数据,确定它是HTTP GET / POST请求,然后将其传递给内置的HTTP处理程序或Gorilla mux?现在,我的代码看起来像这样,我自己在构建http路由逻辑:

func ListenConn() {
    listen, _ := net.Listen("tcp", ":8080")
    defer listen.Close()
    for {
        conn, err := listen.Accept()
        if err != nil {
            logger.Println("listener.go", "ListenConn", err.Error())
        }
        go HandleConn(conn)
    }
}

func HandleConn(conn net.Conn) {
    defer conn.Close()

    // determines if it is an http request

    scanner := bufio.NewScanner(conn)
    for scanner.Scan() {
        ln := scanner.Bytes()
        fmt.Println(ln)
        if strings.Fields(string(ln))[0] == "GET" {
            http.GetRegistrationCode(conn, strings.Fields(string(ln))[1])
            return
        }

        ... raw tcp handler code

    }
}

1 个答案:

答案 0 :(得分:0)

混合HTTP和原始TCP流量不是一个好主意。

考虑一下应用程序和客户端之间的所有防火墙和路由器。它们都旨在实现安全的HTTP传递。他们将如何处理您的TCP流量与有效HTTP进入同一端口的情况?

作为解决方案,您可以将流量拆分到同一应用程序中的两个不同端口。

通过端口分离,您可以独立地路由HTTP和TCP流量,并为每个通道配置适当的网络安全性。

示例代码以侦听2个不同的端口:

getTemplate(url, function(responseText) {
    document.write(responseText);
    // or add the responseText to your div with: yourDiv.innerHTML += responseText;
});

在浏览器中打开package main import ( "fmt" "net" "net/http" "os" ) type httpHandler struct { } func (m *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Println("HTTP request") } func main() { // http go func() { http.ListenAndServe(":8001", &httpHandler{}) }() // tcp l, err := net.Listen("tcp", "localhost:8002") if err != nil { fmt.Println("Error listening:", err.Error()) os.Exit(1) } defer l.Close() for { conn, err := l.Accept() if err != nil { fmt.Println("Error accepting: ", err.Error()) os.Exit(1) } go handleRequest(conn) } } // Handles incoming requests. func handleRequest(conn net.Conn) { // read/write from connection fmt.Println("TCP connection") conn.Close() } ,然后运行命令行http://localhost:8001/来测试监听器