UDP 读取块永远



我在 Go 中做了一个简单的 UDP 结构,当我运行以下代码时,它会永远阻塞。作为参考,我的服务器的地址在运行客户端的同一台计算机上运行,但服务器侦听的端口和地址与客户端绑定的端口和地址不同。

var client Clientee
client.Create("the address of my server")
err, messages := client.Read() // <-- HERE IT BLOCKS FOREVER
if err != nil { panic(err) }
fmt.Printf("Messages: %s", messages)

下面是声明我的结构的代码部分:

package controllers
import (
"fmt"
"net"
"time"
)
const (
BUF_SIZE = 1024
CLIENT_PORT = "4097"
SERVER_PORT = "4096"
)
type Clientee struct {
ClServerAddr *net.UDPAddr
ClLocalAddr *net.UDPAddr
ClConn *net.UDPConn
ClWasShutdown bool
}
// Initialize and connect the Clientee
func (c *Clientee) Create(hostAddr string) error {
var err error
c.ClWasShutdown=false
// Resolve the server's address
c.ClServerAddr, err = net.ResolveUDPAddr("udp", hostAddr+":"+SERVER_PORT)
if err != nil { return err }
fmt.Println("Server addr = ",c.ClServerAddr.String())
// Resolve our local address
c.ClLocalAddr, err = net.ResolveUDPAddr("udp", ":"+CLIENT_PORT)
if err != nil { return err }
// Create the connection
c.ClConn, err = net.ListenUDP("udp", c.ClLocalAddr)
if err != nil { return err }
// Pause
time.Sleep(time.Millisecond*200)
return nil
}
// Send a message to the Server
func (c *Clientee) Send(msg string) error {
_, err := c.ClConn.WriteToUDP([]byte(msg), c.ClServerAddr)
if err!=nil { return err }
return nil
}
// Read messages from the Server
func (c *Clientee) Read() (error, string) {
bfr:=make([]byte, BUF_SIZE) // Make the buffer
n, addr, err := c.ClConn.ReadFromUDP(bfr)
if err!=nil { return err, "" }
// If the message doesn't come from the server, don't return it
if addr.String()!=c.ClServerAddr.String() {
return nil, ""
}
return nil, string(bfr[0:n])
}
// Close the Connection.
func (c *Clientee) Close() error {
return c.ClConn.Close()
}

ReadFromUDP将阻塞,直到收到某些内容。文档将您引向 ReadFrom,其中显示"ReadFrom 实现了 PacketConn ReadFrom 方法"。查看 PacketConn 文档,您会发现以下内容:

ReadFrom 从连接读取数据包,将有效负载复制到 p.它返回复制到 p 中的字节数和返回地址 那是在数据包上。它返回读取的字节数 (0 <= n <= len(p(( 以及遇到的任何错误。调用方应始终处理 n> 0 在考虑错误错误之前返回的字节数。

可以使 ReadFrom 超时并在 固定时限;请参阅 SetDeadline 和 SetReadDeadline。

因此,如果您不希望阻止(根据评论(,那么您可以:

  • 使用SetDeadlineSetReadDeadline设置截止日期。
  • 在 goroutine 中运行ReadFromUDP并在接收数据时处理数据(可能包括将接收到的数据放入通道(

注意:使用零长度缓冲区调用ReadFromUDP可能不会阻塞,但这取决于操作系统实现,因此可能不是可以依赖的。

相关内容

最新更新