Go 在TCP连接的端口上发送UDP数据包

Go 在TCP连接的端口上发送UDP数据包,go,udp,Go,Udp,我有一个Golang TCP服务器,即net.TCPConn,连接在一个端口上,除了TCP流之外,该端口还必须接收UDP数据包并用UDP数据包进行响应。传入的UDP数据包在服务器上弹出(从net.TCPConn.Read()),但我不知道如何再次发送UDP数据包。所有UDP写入方法仅适用于net.UDPConnnet.UDPConn.writemsgludp()诱人地谈论它是应用于连接的套接字还是非连接的套接字,但我不知道如何从net.TCPConn派生net.UDPConn;我尝试将net.T

我有一个Golang TCP服务器,即
net.TCPConn
,连接在一个端口上,除了TCP流之外,该端口还必须接收UDP数据包并用UDP数据包进行响应。传入的UDP数据包在服务器上弹出(从
net.TCPConn.Read()
),但我不知道如何再次发送UDP数据包。所有UDP写入方法仅适用于
net.UDPConn
net.UDPConn.writemsgludp()
诱人地谈论它是应用于连接的套接字还是非连接的套接字,但我不知道如何从
net.TCPConn
派生
net.UDPConn
;我尝试将
net.TCPConn
转换为
net.UDPConn
,但这会引起恐慌

正确的方法是什么

仅供参考,我确实在同一端口上打开了一个UDP侦听器(“因为另一端的客户端可以选择在完全无连接模式下运行”),但由于套接字连接后,UDP数据包到达TCP服务器而不是UDP服务器,我想将UDP响应发送回同一个端口,而不是以某种邪恶的方式将两者混为一谈。还是说不整洁就是答案


编辑:这里是关于系统设计的一个词:这个UDP数据包的目的是测试这个套接字上的连接(服务器只是回显它)。套接字是一个[希望]已建立的SSH端口转发隧道,因此我不想使用另一个套接字,因为这不会测试我要测试的内容(即,套接字和SSH隧道都是打开的;SSH端口转发隧道的一个缺点是,由于应用程序连接到
localhost
,套接字将立即报告已连接,即使服务器当时没有实际连接)。SSH隧道承载TCP流量流,我特别希望使用UDP进行此操作,因为我不希望我的UDP连接测试被卡在TCP流量队列后面;在此应用程序中,计时非常重要,UDP数据包携带时间戳来测量它。如果是有效的套接字操作,Go必须有办法完成…?

如果您只想将UDP数据包发送到通过TCP首先到达您的应用程序的“客户端”,那么您可能需要获得远程:

然后假设此客户端也是服务器,并在
1234

ServerAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:1234", addr))
然后,您可以通过执行以下操作进行回复:

 conn, err := net.DialUDP("udp", nil, ServerAddr)
 if err != nil {
     log.Fatal(err)
 }
 defer close(conn)
 buf := []byte("ping")
 _, err = conn.Write(buf)
我不知道这是否正是你想要的,但希望能给你更多的想法。

在所有问题的讨论变得清晰之后

@JimB说得很对,您不能在TCP端口上发送UDP数据包。我认为这是可能的原因是
sendto()
的定义说:

如果在连接模式(
SOCK\u STREAM
)上使用了
sendto()
SOCK\u SEQPACKET
)套接字,参数
dest\u addr
addrlen
为 已忽略(如果未忽略,则可能会返回错误
EISCONN
NULL
和0),并且在套接字启动时返回错误
ENOTCONN
实际上没有连接

…当我在TCP连接的端口上调用
sendto()
时,我发送的数据确实出现在我的Golang
net.TCPConn
端点。然而,在这种情况下发生的情况是,
sendto()
实际上已经成为
send()
的别名,尽管调用了
sendto()
,发送的数据实际上是在TCP数据包中传输的,而不是UDP数据包。使用
netcat-u$host$port
向服务器发送UDP流量和
netcat$host$port
向服务器发送TCP流量证明了这一点:前者没有在
net.TCPConn
端点生成任何数据,而他是后者


正确的方法是,客户端在同一端口上同时向服务器打开TCP和UDP套接字,而服务器同时侦听TCP和UDP“连接”(UDP连接当然不是连接,它只是与本地端口号的关联)在同一端口上。然后TCP服务器处理我的流,UDP服务器处理我的UDP测试/测量数据包,两者都通过同一SSH端口转发隧道。

UDP不建立连接,通常在使用UDP时,直接处理单独寻址的数据包,因此在接收和发送每个数据包时您还需要接收或通知对等方的IP+端口,以了解您正在与谁通话或信息来自谁。有两个系统调用用于此操作,
recvfrom()
sendto()
,我不知道如何实现此功能,但我非常确定
net.TCPConn.Read()
根本不适用于UDP。您无法从TCP连接发送或接收UDP数据包。如果您需要发送UDP数据包,请使用UDP连接。我知道UDP是无连接的,但它可以通过连接的套接字发送UDP数据包;您只需将目标地址保留在
发送到()
它明白了你的意思。我知道这一点,因为这正是链接的另一端(用C编码)在这种情况下所做的。当然,Golang在其
net
实现中允许了非常正常的套接字操作!?中的注释暗示了它,我只是不知道它是如何工作的。你不能发送UDPTCP连接上的数据包,这没有任何意义。我可以向您保证,您没有在TCP连接上接收到UDP数据包,并且由于ssh隧道是TCP,您无法向其发送UDP数据包。可能有一个UDP套接字侦听同一端口号,但它与TCP连接完全分离。
 conn, err := net.DialUDP("udp", nil, ServerAddr)
 if err != nil {
     log.Fatal(err)
 }
 defer close(conn)
 buf := []byte("ping")
 _, err = conn.Write(buf)