【问题标题】:TCP client not working correcty golangTCP客户端无法正常工作golang
【发布时间】:2017-09-23 08:33:00
【问题描述】:

我有用 golang 编写的 rest-ful 界面。我需要在每个端点上进行身份验证。身份验证完成后,我必须将其转发回 tcp 服务器。 我创建了一个 tcp 客户端,来自通道的任何值都将发送到 tcp 服务器。该通道是从 http 请求正文填充的。 问题是,一旦我发出 curl 命令,客户端就会卡住没有响应;所以很明显我做错了什么,不知道出了什么问题。有人对我的问题有什么见解吗?

 package main

            import (
                "bufio"
                "encoding/json"
                "flag"
                "fmt"
                "io/ioutil"
                "log"
                "net"
                "net/http"
                "net/http/httputil"
                "net/url"
                "os"
                "strconv"

                auth "github.com/abbot/go-http-auth"
            )

            type Configuration struct {
                Server        string
                Port          int64
                UserName      string
                Pwd           string
                Realm         string
                ProxyPort     int64
                Edeserver     string

            }

            var (
                Config *Configuration
                logp   = flag.Bool("log", false, "enable logging")
            )

            func ReadConfiguration() {
                file, _ := os.Open("Config.json")
                decoder := json.NewDecoder(file)
                Config = &Configuration{}
                err := decoder.Decode(&Config)
                if err != nil {
                    fmt.Println("error:", err)
                }

            }

            func Secret(user, realm string) string {
                if user == Config.UserName {
                    // password is "hello"
                    return Config.Pwd
                }
                return ""
            }

            func reverseProxyTows(w http.ResponseWriter, authenticatedRequest *auth.AuthenticatedRequest) {
                req := &authenticatedRequest.Request

                if *logp {
                    log.Println(" Authenticated Username ", authenticatedRequest.Username)
                    log.Println(" Authenticated URL ", req.URL.RequestURI())
                }

                destinationURL := fmt.Sprintf("http://%s:%d", Config.Server, Config.Port)
                u, err := url.Parse(destinationURL)
                if err != nil {
                    log.Fatal(err)
                }

                if *logp {
                    log.Println("reverse_proxy", u)
                }

                reverseProxy := httputil.NewSingleHostReverseProxy(u)

                reverseProxy.ServeHTTP(w, req)
            }

            func openConnectionTotcp(edechannel chan string) {
                conn, _ := net.Dial("tcp", Config.Edeserver)
                text := <-edechannel
                fmt.Fprintf(conn, text+"\n")
                message, _ := bufio.NewReader(conn).ReadString('\n')
                fmt.Print("Message from server: " + message)
            }


            func main() {
                ReadConfiguration()
                flag.Parse()
                c := make(chan string)
                go openConnectionTotcp(c)

                fmt.Printf("Started proxy to destination server %v:%d and is listening on %d ", Config.Server, Config.Port, Config.ProxyPort)

                authenticator := auth.NewBasicAuthenticator(Config.Realm, Secret)
                http.HandleFunc("/", authenticator.Wrap(reverseProxyTows))
                http.HandleFunc("/tyrion/1", authenticator.Wrap(func(w http.ResponseWriter, authenticatedRequest *auth.AuthenticatedRequest) {
                    req := &authenticatedRequest.Request
                    bodyBytes, err2 := ioutil.ReadAll(req.Body)
                    if err2 != nil {
                        log.Fatal(err2)
                    }
                    bodyString := string(bodyBytes)
                    c <- bodyString
                    fmt.Fprintf(w, "success")
                }))
                http.ListenAndServe(":"+strconv.FormatInt(Config.ProxyPort, 10), nil)
            }

【问题讨论】:

  • 您的执行流程似乎在“c
  • 首先,您没有检查来自 net.Dial 或 ReadString 的错误,您没有关闭 tcp 连接,如果您要尝试阅读多条消息,您正在扔掉可能有缓冲数据的bufio.Reader。您也只需调用一次 tcp.Dial 然后退出 goroutine,因此即使它有效,也只能用于第一个 http 请求。

标签: go tcp


【解决方案1】:

您的代码执行在c &lt;- bodyString 处阻塞,因为似乎没有从该无缓冲通道读取任何内容。该行将暂停执行,直到另一个例程从通道中读取。

【讨论】:

  • 不,不是真的 openConnectionTotcp 有一个 chan 参数,并且 go 例程从它读取 func openConnectionTotcp(edechannel chan string) { conn, _ := net.Dial("tcp", Config.Edeserver) text := &lt;-edechannel fmt.Fprintf(conn, text+"\n") message, _ := bufio.NewReader(conn).ReadString('\n') fmt.Print("Message from server: " + message) }
  • 该例程将使用一条消息,然后返回,之后对通道的任何写入都将永远阻塞。您还从 tcp.Dial 中丢弃了错误,所以谁知道该例程中发生了什么。
  • tcp dial 确实有效,因为我正在运行本地 tcp 服务器,并且确实在 tcp 服务器端看到了消息。发出 curl 请求的客户端挂起。 That routine will consume a single message, then return, 将如何返回,因为我首先没有关闭频道
  • 无论是否关闭通道,函数都会返回。知道您的 TCP 侦听器接到呼叫并不能告诉您拨号成功。未经证实的假设会导致缺陷!
猜你喜欢
  • 2018-06-01
  • 2017-08-17
  • 2018-10-12
  • 1970-01-01
  • 2018-09-21
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
相关资源
最近更新 更多