Golang Go语言中 net 包读取数据问题,如何触发 Conn 的可读事件
Golang Go语言中 net 包读取数据问题,如何触发 Conn 的可读事件
刚学 golang ,最近在写一个代理服务器.使用了自带的 net 库来需要实现数据的中转。
服务器有这样一个逻辑:当收到目标服务器的数据时,需要转发给客户端。
但是查了一下资料,net.Conn.Read 方法可以读取来自目标服务器的数据,但是每次都需要手动调用,
我也不想写死循环或者 time.Sleep 之类的轮询。
自带的 net 库虽然底层是多路复用的封装, 但是没有暴露像 netty 一样的事件回调,也没有 java NIO 的可读事件通知,请问该怎么处理这种情况呢?需要依赖第三方包或者自己底层重新写一套? 求各位大佬指教。 [哭]
更多关于Golang Go语言中 net 包读取数据问题,如何触发 Conn 的可读事件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Read 是阻塞调用,没有数据不会返回的。
更多关于Golang Go语言中 net 包读取数据问题,如何触发 Conn 的可读事件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
对啊,但是我需要在有可读数据的第一时间转发到客户端,轮询调用 Read 是可以解决的,但是太难看了。请问有其他办法吗?
自己写个回调不就行了
就用 go 轮询
有数据 Read 就立马返回,你再转发,没有数据就阻塞等待,有什么问题吗?
谢谢,刚学 go,对这个不太熟。如果没有数据调用 Read 会阻塞等待的话,直接找协程里面写死循环就可以了。我去试试。
每个连接开一个协程,之后
callback = function (data) {
}
for {
data = net.Read()
callback(data)
}
搞定,这就是回调
按理说阻塞不是比回调好理解多了么……这就是 go 的卖点啊
主要是我理解错了,以为没数据的时候 read 会直接返回,所以我就以为需要不停的调用查看是否有数据。实际上如果是阻塞到有数据来了才返回的话,就很好理解了。
可以实现啊,自己调 epoll 就行
不过看你回复,原来不知道 Read 是阻塞调用,那可以认为你不懂基本的网络读写了,更不用说 epoll
能力不够的时候,“不想写”,“太难看“这种话,是没有资格说的
syscall.SetNonblock 然后 select 轮询?不知道 go 的范式是不是这样做
谢谢回复。因为没认真研究过 socket,只写过 java nio,epoll 还是知道的,不然我也不会说什么可读事件通知这种话了😂
严重怀疑楼上几位是不是写过 Golang
golang 里面的 tcp proxy 基本上就是 go 两个函数 各自把一个 socket 读通道的数据写到另一个 scoket 的写通道上
参考
https://github.com/kahlys/proxy/blob/master/proxy.go#L74
https://github.com/google/tcpproxy/blob/master/tcpproxy.go#L353
我需要把目标服务器数据进行加密后转发的。不过本质的思路确实如你所说。
你先实现一个加解密的 pipe ( reader + writer )
把 proxy 上在 io.Copy 替换成这个 pipe 就可以了
func proxy ( src. dst net.Conn ) error {
errCh := make(chan error, 1)
go func () {
errCh<- io.Copy(src, dst) // TODO: replace with your pipe
}
go func () {
errCh<- io.Copy(dst, src) // TODO: replace with your pipe
}
return <-errCh
}
抱歉 语法错+错误处理有问题 意思到了吧
人家就是把异步封装成同步的写法给你,你还要去找异步的。。。
在Go语言中,net
包提供了对网络编程的支持,包括TCP、UDP等协议。对于net.Conn
接口的可读事件,Go语言并没有像某些其他编程语言(如C语言的select
系统调用或Python的selectors
模块)那样直接提供可读事件的回调机制。相反,Go语言通常使用goroutine和channel来实现非阻塞的I/O操作。
要触发并处理net.Conn
的可读事件,你可以采取以下步骤:
-
启动一个goroutine来读取数据。在这个goroutine中,你可以使用
conn.Read
方法读取数据。这个方法会阻塞,直到有数据可读或者连接关闭。 -
使用channel来通知其他goroutine数据已经读取完毕或者发生了错误。这样,你就可以在需要处理数据的地方等待这个channel的信号,而不是直接阻塞在
Read
方法上。 -
错误处理:在读取数据时,要检查是否发生了错误(如连接被对方关闭)。如果发生错误,你可以关闭这个连接,并通过channel通知其他goroutine进行相应的处理。
-
超时处理:如果你需要设置读取超时,可以使用
conn.SetReadDeadline
方法。这样,如果读取操作在指定的时间内没有完成,Read
方法会返回一个超时错误。
通过上述方法,你可以有效地处理net.Conn
的可读事件,并在Go语言的并发模型中优雅地管理网络I/O。