如何解决Golang TCP 代理io.Copy在使用 io.Multiwriter 时中断
我目前正在尝试 Go,但无法弄清楚以下内容:
我试图通过我的应用程序代理 MySQL 连接,打算对来自客户端的请求和来自服务器的响应进行一些内省。我对 Redis 连接做了完全相同的事情,效果很好。
现在的问题是,如果我只是这样做
go io.Copy(serverConnection,clientConnection)
go io.Copy(clientConnection,serverConnection)
这很好用。我可以使用 mysql 客户端连接到我的代理并向 MySQL 服务器发出查询和接收响应。
但是,如果我尝试通过写入 io.MultiWriter
来“监视”连接,则连接会挂起,等待初始响应。
实现(简化)如下所示(并以这种方式工作):
package main
import (
"fmt"
"io"
"log"
"net"
)
func main () {
port := 21001
listenAddr,err := net.ResolveTCPAddr("tcp",fmt.Sprintf("127.0.0.1:%d",port))
if err != nil {
log.Fatalln(err)
}
targetAddr,"127.0.0.1:11001")
if err != nil {
log.Fatalln(err)
}
listener,err := net.ListenTCP("tcp",listenAddr)
if err != nil {
log.Fatalln(err)
}
for {
clientConnection,err := listener.AcceptTCP()
if err != nil {
log.Fatalln(err)
}
go func () {
serverConnection,err := net.DialTCP("tcp",nil,targetAddr)
if err != nil {
return
}
connectionDone := make(chan bool)
go monitorClientConnection(clientConnection,serverConnection,connectionDone)
go monitorServerConnection(serverConnection,clientConnection,connectionDone)
_ = <-connectionDone
_ = <-connectionDone
fmt.Println("MySQL connection closed")
}()
}
}
func monitorClientConnection(clientConnection *net.TCPConn,serverConnection *net.TCPConn,connectionDone chan bool) {
go func() {
_,err := io.Copy(serverConnection,clientConnection)
fmt.Println(err)
_ = serverConnection.Close()
connectionDone <- true
}()
}
func monitorServerConnection(serverConnection *net.TCPConn,clientConnection *net.TCPConn,err := io.Copy(clientConnection,serverConnection)
fmt.Println(err)
_ = clientConnection.Close()
connectionDone <- true
}()
}
它开始失败的地方
如果我将监控功能的实现从(客户端和服务器相同,只是颠倒过来):
func monitorServerConnection(serverConnection *net.TCPConn,serverConnection)
fmt.Println(err)
_ = clientConnection.Close()
connectionDone <- true
}()
}
到
func monitorServerConnection(serverConnection *net.TCPConn,connectionDone chan bool) {
_,w := io.Pipe() // The reader here would be used to consume the stream,left out for simplicity
go func() {
mw := io.MultiWriter(clientConnection,w)
_,err := io.Copy(mw,serverConnection)
fmt.Println(err)
_ = clientConnection.Close()
connectionDone <- true
}()
}
它只是挂起。这与适用于 Redis 代理的方法完全相同(Redis 序列化协议是纯文本、换行符分隔的,可能是一个因素?)。
我想知道的
- 据我所知,为什么使用
io.MultiWriter
会导致流挂起? - 有没有更好的方法来“窥探”这个流,或者将它放到一个单独的 goroutine 中,该 goroutine 可以在将流转发到上游服务器的同时读取/解析流?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。