J'ai une structure UDP simple que j'ai créée dans Go, et lorsque j'exécute le code suivant, elle se bloque pour toujours. Pour référence, l'adresse de mon serveur s'exécute sur le même ordinateur exécutant le client, mais le serveur écoute sur un port et une adresse différents de ceux auxquels le client est lié.

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)

Voici la partie du code qui déclare ma structure :

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()
}
-3
user96931 14 févr. 2020 à 02:04

1 réponse

Meilleure réponse

ReadFromUDP se bloquera jusqu'à ce que quelque chose soit reçu. La docs vous renvoie à la ReadFrom qui dit "ReadFrom implémente la méthode PacketConn ReadFrom.". En consultant la documentation de PacketConn, vous trouverez les éléments suivants :

ReadFrom lit un paquet à partir de la connexion, en copiant la charge utile dans p. Il renvoie le nombre d'octets copiés dans p et l'adresse de retour qui figurait sur le paquet. Il renvoie le nombre d'octets lus (0 <= n <= len(p)) et toute erreur rencontrée. Les appelants doivent toujours traiter les n > 0 octets renvoyés avant de considérer l'erreur d'erreur.

ReadFrom peut expirer et renvoyer une erreur avec Timeout() == true après une limite de temps fixe ; voir SetDeadline et SetReadDeadline.

Donc, si vous ne voulez pas que cela se bloque (conformément aux commentaires), vous pouvez soit :

  • Utilisez SetDeadline ou SetReadDeadline pour définir une date limite.
  • Exécutez ReadFromUDP dans une goroutine et traitez les données telles qu'elles sont reçues (ce qui peut inclure la mise des données reçues sur un canal)

Remarque : L'appel de ReadFromUDP avec un tampon de longueur nulle peut ne pas bloquer, mais cela dépend du fonctionnement la mise en œuvre du système n'est donc probablement pas quelque chose sur quoi s'appuyer.

1
Brits 14 févr. 2020 à 01:45