永远的UDP读取块

问题描述 投票:-2回答:1

我有一个用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()
}
go networking udp
1个回答
1
投票

ReadFromUDP将阻塞,直到接收到某些内容为止。 ReadFromUDP会将您引向docs,其中说:“ ReadFrom实现PacketConn ReadFrom方法。”。查看ReadFrom文档,您会发现以下内容:

ReadFrom从连接中读取数据包,将有效负载复制到p。它返回复制到p中的字节数和返回地址在包装上。它返回读取的字节数(0 <= n <=len(p))和遇到的任何错误。呼叫者应始终处理n> 0考虑错误err之前返回的字节数。

ReadFrom可以超时,并在超时后返回Timeout()== true的错误。固定时限;请参阅SetDeadline和SetReadDeadline。

因此,如果您不想阻止它(根据评论),则可以:

  • 使用PacketConnSetDeadline设置截止日期。
  • 在goroutine中运行SetReadDeadline,并在接收到数据时对其进行处理(可能包括将接收到的数据放入通道中)

注意:使用零长度缓冲区调用ReadFromUDP可能不会阻塞,但这取决于ReadFromUDP,因此可能没有依赖。

© www.soinside.com 2019 - 2024. All rights reserved.