英文:
Go - Webserver listening for multiple protocols (HTTP and RTMP) on the same port
问题
我正在尝试在我的Go Web应用程序中实现RTMP协议,但是我似乎无法找到同时处理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
})
fmt.Println("Starting web server")
http.ListenAndServe(":8000", nil)
}
zhangpeihao/gortmp有一个很棒的RTMP模块,示例代码展示了如何通过监听TCP套接字来处理RTMP。但是如何在特定的端点上处理RTMP而不是使用第二个端口呢?
英文:
I'm trying to implement the RTMP protocol to along side my web application in Go, however I can't seem to figure out solution to handle both HTTP and and RTMP on the same port.
The idea would be something such as this.
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)
}
zhangpeihao/gortmp has a great RMTP module with an example that shows handling RTMP by listening on a TCP socket. However how can handle it on a specific endpoint rather then a second port?
答案1
得分: 0
避免将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第一个字节
proxyConn = createLocalConnection(RTMPPort)
} else {
proxyConn = createLocalConnection(HTTPPort)
}
proxyConn.Write(data[:n])
defer proxyConn.Close()
// 请求循环
go func() {
for {
data := make([]byte, 1024*1024)
n, err := conn.Read(data)
if err != nil {
break
}
proxyConn.Write(data[:n])
}
}()
// 响应循环
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)
}
}
这段代码通过读取第一个字节来判断连接的类型,如果是0x03,则创建一个本地RTMP连接,否则创建一个本地HTTP连接。然后,它将数据从客户端连接转发到代理连接,并将响应从代理连接转发回客户端连接。主函数中,它监听TCP连接并在接受到连接时启动代理连接的处理。
英文:
While wanting to avoid having to convert RTMPT to RTMP, and without having to fork other modules, this was my solution in the end by reading the first byte. Full implementation can be found here.
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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论