Go - веб-сервер прослушивает несколько протоколов (HTTP и RTMP) на одном и том же порту
Я пытаюсь реализовать протокол RTMP параллельно с моим веб-приложением на Go, однако я не могу найти решение для обработки как HTTP, так и RTMP на одном и том же порту.
Идея будет что-то вроде этого.
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello!")
})
http.HandleFunc("/rtmp", func(w http.ResponseWriter, r *http.Request) {
// RTMP handling here
})
fmt.Println("Starting web server")
http.ListenAndServe(":8000", nil)
}
https://github.com/zhangpeihao/gortmp есть отличный модуль RMTP с примером, показывающим обработку RTMP путем прослушивания сокета TCP. Однако как справиться с этим на конкретной конечной точке, а не на втором порту?
1 ответ
Решение
Желая избежать необходимости конвертировать RTMPT в RTMP и без необходимости разветвлять другие модули, в конечном итоге это было мое решение, прочитав первый байт. Полная реализация может быть найдена здесь.
func createLocalConnection(port string) *net.TCPConn {
addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:"+port)
if err != nil {
panic(err)
}
conn, err := net.DialTCP("tcp", nil, addr)
if err != nil {
panic(err)
}
return conn
}
func proxyConnection(conn *net.TCPConn) {
defer conn.Close()
data := make([]byte, 1)
n, err := conn.Read(data)
if err != nil {
fmt.Println(err)
return
}
var proxyConn *net.TCPConn
if data[0] == 0x03 { // RTMP first byte.
proxyConn = createLocalConnection(RTMPPort)
} else {
proxyConn = createLocalConnection(HTTPPort)
}
proxyConn.Write(data[:n])
defer proxyConn.Close()
// Request loop
go func() {
for {
data := make([]byte, 1024*1024)
n, err := conn.Read(data)
if err != nil {
break
}
proxyConn.Write(data[:n])
}
}()
// Response loop
for {
data := make([]byte, 1024*1024)
n, err := proxyConn.Read(data)
if err != nil {
break
}
conn.Write(data[:n])
}
}
func main() {
listener, err := net.ListenTCP("tcp", addr)
if err != nil {
panic(err)
}
for {
conn, err := listener.AcceptTCP()
if err != nil {
fmt.Println(err)
continue
}
go server.ProxyConnection(conn)
}
}