在TCP连接的端口上发送UDP数据包[关闭]

我在端口上连接了Golang TCP服务器,即 net.TCPConn </ code> ,除了TCP数据流外,还必须接收UDP数据包并以UDP数据包进行响应。 传入的UDP数据包从服务器弹出(从 net.TCPConn.Read()</ code>),但是我不知道如何再次发送UDP数据包。 所有UDP写入方法仅适用于 net.UDPConn </ code>。 net.UDPConn.WriteMsgUDP()</ code>诱人地讨论了它是应用于已连接的套接字还是未连接的套接字,但是我不知道如何导出 net.UDPConn </ code >来自 net.TCPConn </ code>; 我已经尝试将 net.TCPConn </ code>强制转换为 net.UDPConn </ code>,但这会引起恐慌。</ p>

正确的方法是 这样吗?</ p>

仅供参考,我确实在同一端口上打开了UDP侦听器(因为另一端的客户端可以选择以完全无连接模式运行),但是自从 连接后,UDP数据包到达TCP服务器而不是UDP服务器,我想将UDP响应发送回同一孔,而不必以某种不合时宜的方式将两者混在一起。 </ p>

编辑:这是系统设计上的一个字:此UDP数据包的目的是测试此套接字上的连接(服务器只是将其回显)。 该套接字是一个[希望]建立的SSH端口转发隧道,因此,我不想使用其他套接字,因为这不会测试我要测试的内容(即套接字和SSH隧道均已打开; SSH端口转发隧道的一个缺点是,由于应用程序建立了与 localhost </ code>的连接,因此套接字会立即报告已连接,即使此时服务器实际上并未连接也是如此。 否则,SSH隧道将承载TCP通信流,我特别想为此使用UDP,因为我不希望UDP连接测试滞留在TCP通信队列中。 定时在此应用中很重要,并且UDP数据包带有时间戳以对其进行测量。 在已连接的套接字上发送UDP数据包是有效的套接字操作,Go必须具有 怎么做...?</ p>
</ div>

展开原文

原文

I have a Golang TCP server, i.e. net.TCPConn, connected on a port which, in addition to a TCP stream, also has to receive UDP packets and respond with UDP packets. The incoming UDP packet pops out at the server (from a net.TCPConn.Read()) but I can't figure out how to send a UDP packet back again. All of the UDP write methods apply only to net.UDPConn. net.UDPConn.WriteMsgUDP() tantalisingly talks of whether it is applied to a connected or a non-connected socket, but I can't figure out how to derive net.UDPConn from net.TCPConn; I've tried casting net.TCPConn to net.UDPConn but that causes a panic.

What is the correct way to do this?

FYI, I do have a UDP listener open on the same port ('cos the client at the other end can chose to operate in completely connectionless mode) but since, when the socket is connected, the UDP packet arrives at the TCP server rather than the UDP server, I'd like to send the UDP response back down the same hole, rather than having to mix the two up in some unholy manner. Or is unholiness the answer?

EDIT: a word on the system design here: the purpose of this UDP packet is to test the connection on this socket (the server simply echoes it back). The socket is a [hopefully] established SSH port-forwarding tunnel, hence I don't want to use another socket as this wouldn't test what I'm trying to test (i.e. that both the socket and the SSH tunnel are open; it is a shortcoming of SSH port-forwarding tunnels that, since the application makes a connection to localhost, the socket will report connected immediately, even if the server isn't actually connected at the time). The SSH tunnel otherwise carries a stream of TCP traffic and I specifically want to use UDP for this as I don't want my UDP connection test to be stuck behind the queue of TCP traffic; timing is important in this application and the UDP packet carries timestamps to measure it. Sending a UDP packet on a connected socket is a valid sockets operation, Go must have a way to do it...?

udp
dou4381
dou4381 您不能通过TCP连接发送UDP数据包,这没有任何意义。我可以向您保证,在TCP连接上不会收到UDP数据包,并且由于ssh隧道是TCP,因此您无法向其发送UDP数据包。可能有一个监听相同端口号的UDP套接字,但它与TCP连接完全分开。
2 年多之前 回复
doupu1957
doupu1957 我知道UDP是无连接的,但是它是在连接的套接字下发送UDP数据包的完全有效的套接字。您只需将目标地址保留在sendto()之外,它就能弄清楚您的意思。我知道这一点,因为在这种情况下,这正是用C编码的链接另一端所做的事情。当然,Golang在其网络实现中允许进行相当普通的套接字操作!net.UDPConn.WriteMsgUDP()中的注释暗示它具有,但我不知道它是如何工作的。
2 年多之前 回复
douju1852
douju1852 您无法从TCP连接发送或接收UDP数据包。如果需要发送UDP数据包,请使用UDP连接。
2 年多之前 回复
dongsigan2636
dongsigan2636 UDP不建立连接,通常在使用UDP时,您直接处理数据包,这些数据包是单独寻址的,因此,在接收和发送每个数据包时,您还需要接收或通知对等方的IP+端口以了解您的身份正在与信息或来自谁的消息交谈。有两个用于syscall的调用,recvfrom()和sendto(),我不知道Go是如何实现的,但是我很确定net.TCPConn.Read()根本不适用于UDP。
2 年多之前 回复

2个回答



Golang论坛一切都变得很清楚。</ p>

@JimB完全正确 您不能在TCP端口上发送UDP数据包。 我认为这是可能的原因是 sendto()</ code>的定义是:</ p>


如果 sendto()</ code >用于连接模式( SOCK_STREAM </ code>,
SOCK_SEQPACKET </ code>)套接字上,参数 dest_addr </ code>和 addrlen </ code>

被忽略(如果不是
NULL </ code>和0,可能会返回错误 EISCONN </ code>),并返回错误 ENOTCONN </ code> </ p>
</ blockquote>

...并且当我在TCP连接端口上调用 sendto()</ code>时, 我发送的数据确实在Golang net.TCPConn </ code>端点上出现了。 但是,在这种情况下发生的情况是,在后台, sendto()</ code>实际上已成为 send()</ code>的别名,并且尽管调用了 sendto( )</ code>,发送的数据实际上是通过TCP数据包而不是UDP数据包传输的。 这是通过使用 netcat -u $ host $ port </ code>将UDP流量发送到服务器以及使用 netcat $ host $ port </ code>将TCP流量发送到服务器来证明的: 不会在 net.TCPConn </ code>端点上生成任何数据,而后者在端点上生成。</ p>

正确的方法是让客户端打开TCP < em>和</ em>同时在同一端口上连接到服务器的UDP套接字,而服务器同时侦听TCP和UDP“连接”(当然,UDP连接并不是一个连接, 只是与同一端口上的本地端口号的关联。 然后,TCP服务器处理我的流,而UDP服务器处理我的UDP测试/测量数据包,它们都沿着同一SSH端口转发隧道进行。</ p>
</ div>

展开原文

原文

After a discussion on the Golang forums all has become clear.

@JimB is quite right that you cannot send a UDP packet on a TCP port. The reason I thought this was possible is that the definition of sendto() says:

If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET) socket, the arguments dest_addr and addrlen are ignored (and the error EISCONN may be returned when they are not NULL and 0), and the error ENOTCONN is returned when the socket was not actually connected.

...and when I called sendto() on my TCP connected port the data I sent did indeed turn up at my Golang net.TCPConn end-point. However, what is happening in this scenario is that, under the hood, sendto() has effectively become an alias for send() and, despite calling sendto(), the data sent is actually being transported in a TCP packet and not a UDP packet at all. This was proved by using netcat -u $host $port to send UDP traffic to the server and netcat $host $port to send TCP traffic to the server: the former did not produce any data at the net.TCPConn end-point while the latter did.

The correct way to do this is for the client to open a TCP and a UDP socket to the server on the same port at the same time while the server, likewise, listens simultaneously for TCP and UDP "connections" (the UDP connection is not a connection at all of course, it is simply an association with a local port number) on the same port. The TCP server then handles my stream and the UDP server handles my UDP test/measurement packets, both down the same SSH port forwarding tunnel.



如果您只想将UDP数据包发送到首先通过TCP到达您的应用程序的“客户端”,则可能要做的是 获取远程地址:</ p>

   addr = net.TCPConn.RemoteAddr()
</ code> </ pre>

然后假设此客户端也是服务器,并且在中监听端口 UDP </ code> 1234 </ code> </ p>

  ServerAddr,err:= net.ResolveUDPAddr(“ udp”,fmt.Sprintf(“%s:1234”,addr))
</ 代码> </ pre>

然后您可以通过以下方式写回:</ p>

  conn,err:= net.DialUDP(“ udp”,nil  ,ServerAddr)
如果err!= nil {
log.Fatal(err)
}
延迟close(conn)
buf:= [] byte(“ ping”)
_,err = conn。 写(buf)
</ code> </ pre>

不知道这是否正是您想要的,但希望能给您更多的想法。</ p>
</ div >

展开原文

原文

If you just want to send a UDP packet to a "client" that first reaches your application via TCP, what probably you could is to get the remote address:

addr = net.TCPConn.RemoteAddr()

Then assuming this client is also a server and listening on port UDP in 1234

ServerAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:1234", addr))

Then you could just write back by doing:

 conn, err := net.DialUDP("udp", nil, ServerAddr)
 if err != nil {
     log.Fatal(err)
 }
 defer close(conn)
 buf := []byte("ping")
 _, err = conn.Write(buf)

Don't know if this is exactly what you want but hope can give you some more ideas.

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐