如何在Golang中从服务器端断开服务器和客户端之间的UDP连接?

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

How to drop a UDP connection between server and client from server side in Golang?

问题

我正在尝试找到一种标准的方法来关闭UDP连接中的客户端和服务器之间的连接。

目前,我想到了以下解决方案,但我不确定这是否是一种惯用的方式?

在服务器端(handleClient函数)中,我正在执行conn.WriteTo(nil, Addr),将nil写入UDP地址。在客户端,我检查read()函数是否检索到任何数据,如果读取的字节数为零,则客户端放弃读取。

if n == 0 || err != nil {
    break
}

这是我的简化的Server.go文件:

func handleClient(conn *net.UDPConn) {
    b := make([]byte, 1024)

    n, Addr, err := conn.ReadFrom(b[0:])
    if err != nil {
        panic(err)
    }

    fmt.Println("read:", n, "bytes", Addr.String())
    // 将数据写回客户端,仅用于调试目的
    conn.WriteTo(b[0:n], Addr)
    // 让客户端知道服务器没有更多数据
    conn.WriteTo(nil, Addr)
}

这是我的client.go文件:

conn, err := net.Dial("udp", ":14000")
if err != nil {
    panic(err)
}
defer conn.Close()

conn.Write([]byte("I'm client "))

for {
    b := make([]byte, 512)
    n, err := conn.Read(b)
    if n == 0 || err != nil {
        fmt.Println(">", n, err)
        break
    }
    fmt.Println(string(b))
}
fmt.Println("finished.")

这是我的简化的Server.go文件

这是我的client.go文件

英文:

I'm trying to find a standard way to close a connection between a client and server in a UDP connection.

Currently, I came up with the following solution, however, I'm not sure whether this is an idiomatic way or not?

Basically what I'm doing here on the server-side (handleClient function) is to conn.WriteTo(nil, Addr) which write nil to the UDP address. on the client side I check if the read() function retrieved any data or not, in case the number of the reading byte is zero, the client gives up on reading.

if n ==0 || err != nil {
		break
	}

Here is my simplified Server.go file:

func handleClient(conn *net.UDPConn) {
	b := make([]byte, 1024)

	n, Addr, err := conn.ReadFrom(b[0:])
	if err != nil {
		panic(err)
	}

	fmt.Println("read: ", n, " bytes", Addr.String())
	// write the data back to the client, just for debug purpose
	conn.WriteTo(b[0:n], Addr)
    // let the client know that server has no more data 
    conn.WriteTo(nil, Addr)
}

And this is my client.go file

	conn, err := net.Dial("udp", ":14000")
if err != nil {
	panic(err)
}
defer conn.Close()

conn.Write([]byte("I'm client "))

for {
	b := make([]byte, 512)
	n, err := conn.Read(b)
	if n ==0 || err != nil {
		fmt.Println(">", n, err)
		break
	}
	fmt.Println(string(b))
}
fmt.Println("finished.")

答案1

得分: 1

没有标准的方法来实现这个。UDP是一种无状态协议,所以没有像TCP连接那样的"连接"。例如,DNS没有状态的概念,客户端发送请求,服务器响应,没有维护状态,这通常是UDP的卖点。

应用程序负责维护状态,所以如果你想在UDP之上实现一个有状态的协议,你也必须自己处理关闭这样一个连接的操作。你可以从FTP或TFTP中获取灵感,看看如何实现这一点。或者考虑使用像TCP或QUIC这样的有状态传输层协议来处理有状态的连接。

英文:

There is no standard way to do this. UDP is a stateless protocol so there is no "connection" like you would have with a TCP connection. DNS for example has no concept of a state, a client sends a request and the server will respond, no state is maintained, this is usually the selling point of UDP.

The applications are responsible for maintain state, so if you want a stateful protocol on top of UDP you also have to handle closing such a connection yourself. You might take inspiration from FTP or TFTP on how to implement this. Or consider using a stateful transport layer protocol like TCP or QUIC to handle stateful connections for you.

huangapple
  • 本文由 发表于 2021年12月23日 23:50:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/70464431.html
匿名

发表评论

匿名网友

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

确定