UDP 读取永远阻塞
UDP reading blocks forever
我有一个用 Go 制作的简单 UDP 结构,当我 运行 以下代码时,它会永远阻塞。作为参考,我的服务器地址 运行ning 在同一台计算机上 运行ning 客户端,但服务器侦听的端口和地址与客户端绑定的端口和地址不同。
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
will block until something is received. The docs refer you to ReadFrom which says "ReadFrom implements the PacketConn ReadFrom method.". Looking at the PacketConn 文档您将找到以下内容:
ReadFrom reads a packet from the connection, copying the payload into
p. It returns the number of bytes copied into p and the return address
that was on the packet. It returns the number of bytes read (0 <= n <=
len(p)) and any error encountered. Callers should always process the n > 0
bytes returned before considering the error err.
ReadFrom can be made to time out and return an Error with Timeout() == true after a
fixed time limit; see SetDeadline and SetReadDeadline.
所以如果你不想阻止它(根据评论)那么你可以:
- 使用
SetDeadline
或 SetReadDeadline
设置截止日期。
- 运行
ReadFromUDP
在 goroutine 中处理接收到的数据(可能包括将接收到的数据放入通道)
注意:使用零长度缓冲区调用 ReadFromUDP
可能不会阻塞,但这取决于 operating system implementation,因此可能不值得依赖。
我有一个用 Go 制作的简单 UDP 结构,当我 运行 以下代码时,它会永远阻塞。作为参考,我的服务器地址 运行ning 在同一台计算机上 运行ning 客户端,但服务器侦听的端口和地址与客户端绑定的端口和地址不同。
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
will block until something is received. The docs refer you to ReadFrom which says "ReadFrom implements the PacketConn ReadFrom method.". Looking at the PacketConn 文档您将找到以下内容:
ReadFrom reads a packet from the connection, copying the payload into p. It returns the number of bytes copied into p and the return address that was on the packet. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Callers should always process the n > 0 bytes returned before considering the error err.
ReadFrom can be made to time out and return an Error with Timeout() == true after a fixed time limit; see SetDeadline and SetReadDeadline.
所以如果你不想阻止它(根据评论)那么你可以:
- 使用
SetDeadline
或SetReadDeadline
设置截止日期。 - 运行
ReadFromUDP
在 goroutine 中处理接收到的数据(可能包括将接收到的数据放入通道)
注意:使用零长度缓冲区调用 ReadFromUDP
可能不会阻塞,但这取决于 operating system implementation,因此可能不值得依赖。