如何在Go语言中测量并发UDP服务器和客户端的RTT/延迟?

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

How to measure RTT/Latency in a concurrent UDP server and clients created in GoLang?

问题

我能够运行一个并发的UDP服务器并连接UDP客户端到这个并发服务器。然而,我想知道如何测量这个UDP服务器的延迟。

由于某种原因,Linux中的Netcat命令不起作用,而且它们在TCP上运行得很好。我似乎无法测量延迟,因为我正在我的机器上托管这个服务器,并且我正在尝试测量延迟。此外,许多UDP客户端可以同时连接到UDP服务器,似乎有一个非常高的限制。

我应该创建一个Docker容器,然后在路由器上运行它,并测量到路由器的延迟吗?你会如何处理这个问题?

以下是UDP Web服务器的代码:

package main

import (
    "fmt"
    "math/rand"
    "net"
    "os"
    "strconv"
    "strings"
    "time"
)

func random(min, max int) int {
    return rand.Intn(max-min) + min
}

func main() {
    arguments := os.Args
    if len(arguments) == 1 {
        fmt.Println("Please provide a port number!")
        return
    }
    PORT := ":" + arguments[1]

    s, err := net.ResolveUDPAddr("udp4", PORT)
    if err != nil {
        fmt.Println(err)
        return
    }

    connection, err := net.ListenUDP("udp4", s)
    if err != nil {
        fmt.Println(err)
        return
    }

    defer connection.Close()
    buffer := make([]byte, 1024)
    rand.Seed(time.Now().Unix())

    for {
        n, addr, err := connection.ReadFromUDP(buffer)
        go func() {
            fmt.Print("-> ", string(buffer[0:n-1]))
            fmt.Println(addr.String())
            if strings.TrimSpace(string(buffer[0:n])) == "STOP" {
                fmt.Println("Exiting UDP server!")
                return
            }

            data := []byte(strconv.Itoa(random(1, 1001)))
            fmt.Printf("data: %s\n", string(data))
            _, err = connection.WriteToUDP(data, addr)
            if err != nil {
                fmt.Println(err)
                return
            }
        }()
    }
}

以下是UDP客户端的代码:

package main

import (
    "fmt"
    "net"
    "os"
    "time"
)

func check(err error) {
    if err != nil {
        panic(err)
    }
}

func main() {
    arguments := os.Args
    if len(arguments) == 1 {
        fmt.Println("Please provide a host:port string")
        return
    }
    CONNECT := arguments[1]

    s, err := net.ResolveUDPAddr("udp4", CONNECT)
    check(err)
    c, err := net.DialUDP("udp4", nil, s)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Printf("The UDP server is %s\n", c.RemoteAddr().String())
    defer c.Close()

    for {
        time.Sleep(1 * time.Second)
        go func() {
            text := []byte("heyyyy")
            _, err := c.Write(text)
            if err != nil {
                fmt.Println(err)
                return
            }

            buffer := make([]byte, 1024)
            n, _, err := c.ReadFromUDP(buffer)
            if err != nil {
                fmt.Println(err)
                return
            }
            fmt.Printf("Reply: %s\n", string(buffer[0:n]))

        }()

    }
}

希望对你有所帮助!

英文:

I was able to run a concurrent UDP server and connect UDP clients to this concurrent server. However, I would like to know how to measure the latency of this UDP server.

For some reason, Netcat commands in Linux do not work and they work well with TCP. I can't seem to measure it because I am hosting this server on my machine and I am trying to measure the latency. Additionally, a lot of UDP clients can connect to the UDP server concurrently, there seems to be a very high limit.

Should I instead create a docker container and run it on a router and then measure the latency to the router? How would you proceed with this?

Below is the code for the UDP Web server:

package main
import (
"fmt"
"math/rand"
"net"
"os"
"strconv"
"strings"
"time"
)
func random(min, max int) int {
return rand.Intn(max-min) + min
}
func main() {
arguments := os.Args
if len(arguments) == 1 {
fmt.Println("Please provide a port number!")
return
}
PORT := ":" + arguments[1]
s, err := net.ResolveUDPAddr("udp4", PORT)
if err != nil {
fmt.Println(err)
return
}
connection, err := net.ListenUDP("udp4", s)
if err != nil {
fmt.Println(err)
return
}
defer connection.Close()
buffer := make([]byte, 1024)
rand.Seed(time.Now().Unix())
for {
n, addr, err := connection.ReadFromUDP(buffer)
go func() {
fmt.Print("-> ", string(buffer[0:n-1]))
fmt.Println(addr.String())
if strings.TrimSpace(string(buffer[0:n])) == "STOP" {
fmt.Println("Exiting UDP server!")
return
}
data := []byte(strconv.Itoa(random(1, 1001)))
fmt.Printf("data: %s\n", string(data))
_, err = connection.WriteToUDP(data, addr)
if err != nil {
fmt.Println(err)
return
}
}()
}
}

Below is the code for the UDP clients:

package main
import (
"fmt"
"net"
"os"
"time"
)
func check(err error) {
if err != nil {
panic(err)
}
}
func main() {
arguments := os.Args
if len(arguments) == 1 {
fmt.Println("Please provide a host:port string")
return
}
CONNECT := arguments[1]
s, err := net.ResolveUDPAddr("udp4", CONNECT)
check(err)
c, err := net.DialUDP("udp4", nil, s)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("The UDP server is %s\n", c.RemoteAddr().String())
defer c.Close()
for {
time.Sleep(1 * time.Second)
go func() {
text := []byte("heyyyy")
_, err := c.Write(text)
if err != nil {
fmt.Println(err)
return
}
buffer := make([]byte, 1024)
n, _, err := c.ReadFromUDP(buffer)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Reply: %s\n", string(buffer[0:n]))
}()
}
}

答案1

得分: 1

我能够运行一个并发的UDP服务器并连接UDP客户端到这个并发服务器。然而,我想知道如何测量这个UDP服务器的延迟。

为了测量单向延迟,你需要在UDP数据段的负载中发送一个时间戳,然后在接收端检查经过的时间。

要获取RTT延迟,你可以在负载中发送时间戳,让接收端将数据包反弹回来,在发送端接收它,然后最后检查经过的时间。

在网络上测量单向延迟会很困难,因为你需要在发送主机和接收主机中拥有高精确度的同步时钟。因此,在网络上,通常人们只测量抖动和RTT延迟,而不是单向延迟。

关于Linux中Netcat命令无法工作的问题,Netcat确实可以与UDP一起正常工作。也许你忘记了使用-u开关?

$ nc -l -u -p 8080 &
[1] 2171
$ echo hi | nc -u localhost 8080
hi

你无法测量延迟是因为你将服务器托管在自己的机器上,并且你正在尝试测量延迟。此外,很多UDP客户端可以同时连接到UDP服务器,似乎有一个非常高的限制。

为了准确使用术语,UDP是一种无连接的协议,所以我们通常不说使用UDP进行连接,而是说只是发送和接收数据报。

英文:

> I was able to run a concurrent UDP server and connect UDP clients to this concurrent server. However, I would like to know how to measure the latency of this UDP server.

In order to measure one-way latency you will need to send a timestamp in the UDP segment payload and then check the elapsed time in the receiver.

To get the RTT latency, you can send the timestamp in the payload, make the receiver to bounce the packet back, receive it at the sender and then finally check the elapsed time.

Measuring one-way latency across network would be hard since you would need high accurately synchronized clocks in the sender host and the receiver host. Hence across networks, usually people measure only jitter and RTT latency, not one-way latency.

> For some reason, Netcat commands in Linux do not work and they work well with TCP.

netcat does work well with UDP. Maybe you missed the -u switch?

$ nc -l -u -p 8080 &
[1] 2171
$ echo hi | nc -u localhost 8080
hi

> I can't seem to measure it because I am hosting this server on my machine and I am trying to measure the latency. Additionally, a lot of UDP clients can connect to the UDP server concurrently, there seems to be a very high limit.

Just for the sake of accurate terminology, UDP is a connectionless protocol, so we usually don't speak of connecting with UDP, but speak of just sending and receiving datagrams.

huangapple
  • 本文由 发表于 2022年4月28日 05:25:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/72035458.html
匿名

发表评论

匿名网友

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

确定