英文:
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
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论