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)
  }
}
Другие вопросы по тегам