gpt4 book ai didi

sockets - 使用 select 进行非阻塞读取

转载 作者:IT王子 更新时间:2023-10-29 01:45:23 27 4
gpt4 key购买 nike

假设我们有以下服务器抽象(XMPP,但在这里它并不重要):

type Server struct {
Addr string
Conn net.Conn
tlsCon *tls.Conn
R *bufio.Reader
SSL bool
reader chan string
}

还有一个辅助函数来初始化它:

func createServer(domain string) (s *Server, err error) {
conn, err := net.Dial("tcp", domain+":5222")
if err != nil {
return nil, err
}
s = &Server{domain, conn, nil, bufio.NewReader(conn), false, make(chan string, 8)}
go func(t *Server) {
for {
buf := bufsPool.Get().([]byte)
n, err := s.R.Read(buf)
if err == nil {
s.reader <- string(buf[:n])
} else {
fmt.Println(err)
}
}
}(s)

return s, err
}

这个想法很简单:创建一个连接,如果一切顺利,为其获取一个缓冲读取器(我不使用 conn.read 函数只是因为,如果服务器需要,我启动 TLS 连接并将 R 重新分配给reader 是基于它创建的,但现在不是这样了)。

现在我们有两个函数,写入和读取:

func (s *Server) read() (t string) {
t = ""
Inn:
for {
select {
case u := <-s.reader:
fmt.Println("debug", u)
t += u
default:
break Inn
}
}
return t
}

所以我希望读取函数接收 goroutine 发送的数据,该 goroutine 从 chan 的套接字(在 createServer() 中启动的套接字)读取。这个想法是调用写入而不是读取响应。我创建所有这些是因为服务器有时会分两部分发送响应,例如我必须做传统的 read() 2 次。但这没有用,我的读取函数(见上文)什么也没有返回。最有可能的是,那是因为服务器没有设法发回数据,我的函数退出了,因为 chan 中没有任何内容。但一个问题是,尽管我多次调用 write 和 read,但 read 始终不返回任何内容。

所以我想我有一些一般的设计错误,问题是社区是否可以帮助我找到它。谢谢。

最佳答案

问题是您的 select 选择了默认分支,因为读者 channel 中还没有任何内容,所以它立即中断了 for。 ( https://golang.org/ref/spec#Select_statements )

您希望 read 阻塞,直到您收到足够的数据。例如。如果您知道您的回复需要以“\n”结尾,请继续阅读并且在您收到“\n”或 channel 关闭之前不要中断。

也许更好的解决方案是使用 bufio.Scanner在与阅读器的 goroutine 中,如果传入数据以换行符分隔,则使用 chan string 将整个字符串传递给另一个 goroutine。

您还可以使用 Scanner.Split设置不同的拆分器功能。

(另请参阅有关 tcp 和定界符的问答:Golang: TCP client/server data delimiter)

编辑:使用 xml.Decoder.Token您可以继续从流中读取 token ,并适本地处理它们。您可以将其与 Decode 结合使用(这将解码下一个标记)或 DecodeElement (这允许您解码刚刚读取的 token )以解码 xml。

关于sockets - 使用 select 进行非阻塞读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36195197/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com