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

时间:2018-04-13 22:28:15

标签: go udp

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

这样做的正确方法是什么?

仅供参考,我确实在同一个端口上打开了UDP监听器('另一端的客户端可以选择以完全无连接模式运行),但是当连接套接字时,UDP数据包到达在TCP服务器而不是UDP服务器上,我想将UDP响应发送回同一个洞,而不是以某种邪恶的方式将它们混合起来。或者是不通常的答案?

编辑:关于系统设计的一句话:这个UDP数据包的目的是测试这个套接字上的连接(服务器简单地回复它)。套接字是[希望]建立的SSH端口转发隧道,因此我不想使用另一个套接字,因为这不会测试我尝试测试的内容(即套接字和套接字) SSH隧道是开放的;这是SSH端口转发隧道的一个缺点,由于应用程序与localhost建立连接,即使服务器实际上没有连接,套接字也会立即报告连接时间)。 SSH隧道否则携带TCP流量流,我特别想使用UDP,因为我不希望我的UDP连接测试被卡在TCP流量队列之后;时序在此应用程序中很重要,UDP数据包带有时间戳来测量它。 Sending a UDP packet on a connected socket是一个有效的套接字操作,Go必须有办法做到这一点......?

2 个答案:

答案 0 :(得分:1)

如果您只想将UDP数据包发送给"客户端"首先通过TCP到达你的应用程序,你可能会得到远程address

addr = net.TCPConn.RemoteAddr()

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

中侦听端口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)

不知道这是不是你想要的,但希望可以给你一些更多的想法。

答案 1 :(得分:1)

关于Golang forums的讨论后,一切都变得清晰了。

@JimB非常正确,您无法在TCP端口上发送UDP数据包。我认为这是可能的原因是sendto()的定义说:

  

如果在连接模式sendto()上使用SOCK_STREAM,   SOCK_SEQPACKET)套接字,参数dest_addraddrlen是   忽略(错误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端口转发隧道中。