UDP блокирует чтение навсегда - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть простая структура UDP, которую я создал в Go, и когда я запускаю следующий код, он блокируется навсегда. Для справки: адрес моего сервера работает на том же компьютере, на котором работает клиент, но сервер прослушивает порт и адрес, отличные от того, к которому привязан клиент.

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()
}

1 Ответ

1 голос
/ 14 февраля 2020

ReadFromUDP будет блокироваться, пока что-то не будет получено. В документах содержится ссылка на ReadFrom , в котором говорится, что «ReadFrom реализует метод ReadFrom PacketConn.». Просматривая документы PacketConn , вы обнаружите следующее:

ReadFrom читает пакет из соединения, копируя полезную нагрузку в p. Он возвращает количество байтов, скопированных в p, и адрес возврата, который был в пакете. Он возвращает количество прочитанных байтов (0 <= n <= len (p)) и обнаруженную ошибку. Вызывающие абоненты должны всегда обрабатывать n> 0 байтов, возвращенных до рассмотрения ошибки err.

Функция ReadFrom может быть настроена на тайм-аут и вернуть ошибку с Timeout () == true после фиксированного ограничения по времени; см. SetDeadline и SetReadDeadline.

Так что, если вы не хотите, чтобы это блокировалось (согласно комментариям), тогда вы можете либо:

  • Использовать SetDeadline или SetReadDeadline установить крайний срок.
  • Выполнить ReadFromUDP в рамках процедуры и обрабатывать данные по мере их получения (что может включать в себя помещение полученных данных в канал)

Примечание: вызов ReadFromUDP с буфером нулевой длины может не блокироваться, но это зависит от реализации операционной системы , поэтому, вероятно, не стоит на это полагаться.

...