Buffered reader VS listenUDP

huangapple go评论93阅读模式
英文:

Buffered reader VS listenUDP

问题

如果我使用buffered reader来无限等待服务器的消息,这不就和使用ListenUDP差不多吗?

但是如果使用ListenUDP,那我就创建了另一个服务器...

从这个buffered reader中无限收集消息是不是不好的做法,或者说这通常是客户端的做法吗?

client.go

package main

import (
    "fmt"
    "time"
    "net"
    "sync"
    "bufio"
)

func xyz(conn net.Conn, p []byte) {
    rd := bufio.NewReader(conn)
    for {
        fmt.Printf("line\n")
        _, err := rd.Read(p)
        if err == nil {
            fmt.Printf("SERVER : %s\n", p)
        } else {
            fmt.Printf("Some error %v\n", err)
        }
    }
}

func main() {
    var wg = &sync.WaitGroup{}
    p :=  make([]byte, 2048)
    conn, err := net.Dial("udp", "127.0.0.1:1234")
    if err != nil {
        fmt.Printf("Some error %v", err)
        return
    }
    wg.Add(1)
    go xyz(conn, p)
    time.Sleep(2 * time.Second);
    fmt.Fprintf(conn, "Give me a hash to work on ...")
    time.Sleep(4 * time.Second)
    wg.Wait()
}

server.go

package main

import (
    "fmt"
    "net"
)

func sendResponse(conn *net.UDPConn, addr *net.UDPAddr, hash string) {
    _,err := conn.WriteToUDP([]byte("Hello, here is the hash  - " + hash), addr)
    if err != nil {
        fmt.Printf("Couldn't send response %v", err)
    }
}

func main() {
    hash := "36";
    p := make([]byte, 2048)
    addr := net.UDPAddr{
        Port: 1234,
        IP: net.ParseIP("127.0.0.1"),
    }
    ser, err := net.ListenUDP("udp", &addr)
    if err != nil {
        fmt.Printf("Some error %v\n", err)
        return
    }
    for {
        _, remoteaddr, err := ser.ReadFromUDP(p)
        fmt.Printf("CLIENT : %v : %s\n", remoteaddr, p)
        if err !=  nil {
            fmt.Printf("Some error  %v", err)
            continue
        }
        go sendResponse(ser, remoteaddr, hash)
    }
}
英文:

If I am "infinitely" using the buffered reader to wait for messages from the server, is this not pretty much the same as using ListenUDP?

But if use ListenUDP, then I've created another server ...

Is it bad practice to "infinitely" collect from this buffered reader or is that in general how it is done with the client?

client.go

package main

import (
    "fmt"
    "time"
    "net"
    "sync"
    "bufio"
)

func xyz(conn net.Conn, p []byte) {
    rd := bufio.NewReader(conn)
    for {
        fmt.Printf("line\n")
        _, err := rd.Read(p)
        if err == nil {
            fmt.Printf("SERVER : %s\n", p)
        } else {
            fmt.Printf("Some error %v\n", err)
        }
    }
}

func main() {
    var wg = &sync.WaitGroup{}
    p :=  make([]byte, 2048)
    conn, err := net.Dial("udp", "127.0.0.1:1234")
    if err != nil {
        fmt.Printf("Some error %v", err)
        return
    }
    wg.Add(1)
    go xyz(conn, p)
    time.Sleep(2 * time.Second);
    fmt.Fprintf(conn, "Give me a hash to work on ...")
    time.Sleep(4 * time.Second)
    wg.Wait()
}

server.go

package main

import (
    "fmt"
    "net"
)

func sendResponse(conn *net.UDPConn, addr *net.UDPAddr, hash string) {
    _,err := conn.WriteToUDP([]byte("Hello, here is the hash  - " + hash), addr)
    if err != nil {
        fmt.Printf("Couldn't send response %v", err)
    }
}

func main() {
    hash := "36";
    p := make([]byte, 2048)
    addr := net.UDPAddr{
        Port: 1234,
        IP: net.ParseIP("127.0.0.1"),
    }
    ser, err := net.ListenUDP("udp", &addr)
    if err != nil {
        fmt.Printf("Some error %v\n", err)
        return
    }
    for {
        _, remoteaddr, err := ser.ReadFromUDP(p)
        fmt.Printf("CLIENT : %v : %s\n", remoteaddr, p)
        if err !=  nil {
            fmt.Printf("Some error  %v", err)
            continue
        }
        go sendResponse(ser, remoteaddr, hash)
    }
}

答案1

得分: 1

你不需要使用bufio.Reader来从net.Conn读取数据,在UDP连接的情况下,它只会引起问题。

UDP不是基于流的,所以你总是需要读取每个单独的数据报。在最好的情况下,bufio.Reader只是多余地缓冲数据一次,而在最坏的情况下,缓冲区接近满时,你只能得到部分读取,导致数据丢失。一旦多个数据报被缓冲,你也无法区分这些消息,除非它们包含额外的帧。

直接从net.Conn中读取到你的[]byte中:

for {
    n, err := conn.Read(p)
    fmt.Printf("SERVER: %s\n", p[:n])
    if err != nil {
        fmt.Printf("Some error %v\n", err)
        return
    }
}
英文:

You don't need to use a bufio.Reader to read from a net.Conn, and in the case of a UDP connection, it can only cause problems.

UDP is not stream based, so you will always need to read each individual datagram. In the best case a bufio.Reader is just buffering the data one extra time, in the worst case the buffer is near full and you only get a partial read, losing data. You also can no longer differentiate the messages once multiple datagrams have been buffered unless they contain additional framing.

Just read directly from the net.Conn into your []byte:

for {
    n, err := conn.Read(p)
    fmt.Printf("SERVER : %s\n", p[:n])
    if err != nil {
        fmt.Printf("Some error %v\n", err)
        return
    }
}

huangapple
  • 本文由 发表于 2017年4月21日 12:38:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/43534073.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定