我為 tcp 和 udp 連接撰寫了簡單的服務器和客戶端
package main
//server.go
import (
"fmt"
"net"
"os"
"os/signal"
"syscall"
)
func main() {
tcp := 0
udp := 0
defer func(o, t *int) {
fmt.Println(*o, *t)
}(&tcp, &udp)
go func() {
l, err := net.ListenTCP("tcp", &net.TCPAddr{
IP: net.ParseIP("0.0.0.0"),
Port: 3000,
})
if err != nil {
panic(err)
}
b := make([]byte, 24)
for {
conn, err := l.Accept()
if err != nil {
continue
}
n, err := conn.Read(b)
if err != nil {
continue
}
r := string(b[:n])
if r == "close" {
conn.Close()
break
} else {
_, err = conn.Write([]byte("pong"))
if err != nil {
continue
}
}
conn.Close()
tcp
}
l.Close()
}()
go func() {
conn, err := net.ListenUDP("udp", &net.UDPAddr{
IP: net.ParseIP("0.0.0.0"),
Port: 3000,
})
if err != nil {
panic(err)
}
b := make([]byte, 24)
for {
n, addr, err := conn.ReadFromUDP(b)
if err != nil {
continue
}
r := string(b[:n])
if r == "close" {
break
} else {
_, err = conn.WriteToUDP([]byte("pong"), addr)
if err != nil {
continue
}
}
udp
}
conn.Close()
}()
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
<-signals
}
package main
//client.go
import (
"fmt"
"net"
"os"
"os/signal"
"strconv"
"sync/atomic"
"syscall"
"time"
)
func main() {
t := "tcp"
m := "ping"
c := 1
if len(os.Args) > 1 {
t = os.Args[1]
}
if len(os.Args) > 2 {
m = os.Args[2]
}
if len(os.Args) > 3 {
c, _ = strconv.Atoi(os.Args[3])
}
tcp := int64(0)
udp := int64(0)
defer func(o, t *int64) {
fmt.Println(*o, *t)
}(&tcp, &udp)
if c == 1 {
if t == "tcp" {
addr, err := net.ResolveTCPAddr("tcp", ":3000")
if err != nil {
panic(err)
}
conn, err := net.DialTCP("tcp", nil, addr)
if err != nil {
panic(err)
}
_, err = conn.Write([]byte(m))
if err != nil {
panic(err)
}
tcp
}
if t == "udp" {
addr, err := net.ResolveUDPAddr("udp", ":3000")
if err != nil {
panic(err)
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
panic(err)
}
_, err = conn.Write([]byte(m))
if err != nil {
panic(err)
}
udp
}
os.Exit(0)
}
for i := 0; i < c; i {
go func() {
a1, err := net.ResolveTCPAddr("tcp", ":3000")
if err != nil {
panic(err)
}
c1, err := net.DialTCP("tcp", nil, a1)
if err != nil {
panic(err)
}
_, err = c1.Write([]byte(m))
if err != nil {
panic(err)
}
buf := make([]byte, 24)
n, err := c1.Read(buf)
if err != nil {
panic(err)
}
if string(buf[:n]) != "pong" {
panic(1)
}
err = c1.Close()
if err != nil {
panic(err)
}
g := atomic.AddInt64(&tcp, 1)
if g % 100 == 0 {
fmt.Println("tcp", g)
time.Sleep(time.Millisecond * 1000)
}
}()
go func() {
a2, err := net.ResolveUDPAddr("udp", ":3000")
if err != nil {
panic(err)
}
c2, err := net.DialUDP("udp", nil, a2)
if err != nil {
panic(err)
}
_, err = c2.Write([]byte(m))
if err != nil {
panic(err)
}
buf := make([]byte, 24)
n, err := c2.Read(buf)
if err != nil {
panic(err)
}
if string(buf[:n]) != "pong" {
panic(1)
}
err = c2.Close()
if err != nil {
panic(err)
}
g := atomic.AddInt64(&udp, 1)
if g % 100 == 0 {
fmt.Println("udp", g)
time.Sleep(time.Millisecond * 1000)
}
}()
}
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
<-signals
}
并得到一個奇怪的行為:并非所有 udp 請求都在許多連接上發送或處理。
當我發送 100 或 200 時,服務器和客戶端都告訴我所有請求都有效,但是從 1000 開始,服務器和客戶端在 udp 上都有一個奇怪的約 5% 的請求丟失,但沒有恐慌。
我知道 udp 允許丟包,但 localhost 請求的 5% 似乎是一個錯誤。
uj5u.com熱心網友回復:
眾所周知,UDP 是無連接的,因此丟包可能是由 UDP 的這種性質造成的。可能有幾種方法可以降低丟包率。
- 降低客戶端發送資料包的速率
- 呼叫
SetWriteBuffer以增加客戶端的緩沖區大小并設定SetReadBuffer以增加服務器端的緩沖區大小
conn, err := net.DialUDP("udp", nil, addr)
err = conn.SetWriteBuffer(64 * 1024 * 1024)
- 通過查看系統網路資訊
netstat -s -udp,獲取UDP統計資訊。您可以嘗試在服務器端更改rmem_max和的默認值。rmem_default詳情請參考1和2
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/522795.html
標籤:去UDP
