mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 19:17:38 +08:00
feat: use udp to simulate icmp echo
This commit is contained in:
parent
9946b404ae
commit
d72696a0c8
@ -67,10 +67,10 @@ func (c *QQClient) ConnectionQualityTest() *ConnectionQualityInfo {
|
|||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
res := utils.RunICMPPingLoop(&net.IPAddr{IP: c.servers[c.currServerIndex].IP}, 10)
|
res := utils.RunICMPPingLoop(c.servers[c.currServerIndex].IP.String(), 10)
|
||||||
r.ChatServerPacketLoss = res.PacketsLoss
|
r.ChatServerPacketLoss = res.PacketsLoss
|
||||||
if c.highwaySession.AddrLength() > 0 {
|
if c.highwaySession.AddrLength() > 0 {
|
||||||
res = utils.RunICMPPingLoop(&net.IPAddr{IP: c.highwaySession.SsoAddr[0].AsNetIP()}, 10)
|
res = utils.RunICMPPingLoop(c.highwaySession.SsoAddr[0].AsNetIP().String(), 10)
|
||||||
r.SrvServerPacketLoss = res.PacketsLoss
|
r.SrvServerPacketLoss = res.PacketsLoss
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
104
utils/icmp.go
104
utils/icmp.go
@ -1,73 +1,79 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/net/icmp"
|
|
||||||
"golang.org/x/net/ipv4"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ICMPPingResult struct {
|
type ICMPPingResult struct {
|
||||||
PacketsSent int
|
PacketsSent int
|
||||||
PacketsRecv int
|
|
||||||
PacketsLoss int
|
PacketsLoss int
|
||||||
Rtts []int64
|
AvgTimeMill int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunICMPPingLoop(addr *net.IPAddr, count int) *ICMPPingResult {
|
// RunICMPPingLoop unix 下的 ping
|
||||||
if count <= 0 {
|
func RunICMPPingLoop(ip string, count int) (r ICMPPingResult) {
|
||||||
return nil
|
r = ICMPPingResult{
|
||||||
}
|
|
||||||
r := &ICMPPingResult{
|
|
||||||
PacketsSent: count,
|
PacketsSent: count,
|
||||||
Rtts: make([]int64, count),
|
PacketsLoss: count,
|
||||||
|
AvgTimeMill: 9999,
|
||||||
}
|
}
|
||||||
for i := 1; i <= count; i++ {
|
if count <= 0 {
|
||||||
rtt, err := SendICMPRequest(addr, i)
|
return
|
||||||
if err != nil {
|
}
|
||||||
r.PacketsLoss++
|
durs := make([]int64, 0, count)
|
||||||
r.Rtts[i-1] = 9999
|
for i := 0; i < count; i++ {
|
||||||
continue
|
d, err := pingudp(ip)
|
||||||
|
if err == nil {
|
||||||
|
r.PacketsLoss--
|
||||||
|
durs = append(durs, d)
|
||||||
}
|
}
|
||||||
r.PacketsRecv++
|
|
||||||
r.Rtts[i-1] = rtt
|
|
||||||
time.Sleep(time.Millisecond * 100)
|
|
||||||
}
|
}
|
||||||
return r
|
|
||||||
|
if len(durs) > 0 {
|
||||||
|
r.AvgTimeMill = 0
|
||||||
|
for _, d := range durs {
|
||||||
|
r.AvgTimeMill += d
|
||||||
|
}
|
||||||
|
if len(durs) > 1 {
|
||||||
|
r.AvgTimeMill /= int64(len(durs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendICMPRequest(addr *net.IPAddr, seq int) (int64, error) {
|
func pingudp(ip string) (int64, error) {
|
||||||
data := make([]byte, 32)
|
var buf [256]byte
|
||||||
rand.Read(data)
|
ch := make(chan error, 1)
|
||||||
body := &icmp.Echo{
|
|
||||||
ID: 0,
|
port := rand.Intn(10000) + 50000
|
||||||
Seq: seq,
|
conn, err := net.Dial("udp", ip+":"+strconv.Itoa(port))
|
||||||
Data: data,
|
|
||||||
}
|
|
||||||
msg := &icmp.Message{
|
|
||||||
Type: ipv4.ICMPTypeEcho,
|
|
||||||
Code: 0,
|
|
||||||
Body: body,
|
|
||||||
}
|
|
||||||
msgBytes, _ := msg.Marshal(nil)
|
|
||||||
conn, err := net.DialIP("ip4:icmp", nil, addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "dial icmp conn error")
|
return 9999, err
|
||||||
}
|
}
|
||||||
defer func() { _ = conn.Close() }()
|
|
||||||
if _, err = conn.Write(msgBytes); err != nil {
|
t := time.Now().UnixMilli()
|
||||||
return 0, errors.Wrap(err, "write icmp packet error")
|
|
||||||
}
|
_, err = conn.Write([]byte("fill"))
|
||||||
start := time.Now()
|
|
||||||
_ = conn.SetReadDeadline(time.Now().Add(time.Second * 2))
|
|
||||||
buff := make([]byte, 1024)
|
|
||||||
_, err = conn.Read(buff)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "read icmp conn error")
|
return 0, err
|
||||||
}
|
}
|
||||||
duration := time.Since(start).Milliseconds()
|
go func() {
|
||||||
return duration, nil
|
_, err := conn.Read(buf[:])
|
||||||
|
ch <- err
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-time.NewTimer(time.Second * 4).C:
|
||||||
|
err = errors.New("timeout")
|
||||||
|
case err = <-ch:
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil && err.Error() == "timeout" {
|
||||||
|
return 9999, err
|
||||||
|
}
|
||||||
|
return time.Now().UnixMilli() - t, nil
|
||||||
}
|
}
|
||||||
|
12
utils/icmp_test.go
Normal file
12
utils/icmp_test.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPing(t *testing.T) {
|
||||||
|
r := RunICMPPingLoop("127.0.0.1", 4)
|
||||||
|
if r.PacketsLoss == r.PacketsSent {
|
||||||
|
t.Fatal(r)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user