我有一个Golang TCP服务器,即net.TCPConn
,连接在一个端口上,除了TCP流之外,该端口还必须接收UDP数据包并使用UDP数据包进行响应。传入的UDP数据包在服务器上弹出(来自net.TCPConn.Read()
),但我无法弄清楚如何再次发送UDP数据包。所有UDP写入方法仅适用于net.UDPConn
。 net.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必须有办法做到这一点......?
答案 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_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端口转发隧道中。