问题
I am doing a client-server voice chat program(unmanaged C++,win32) in which clients connects to the server using TCP and textchat/chatroom functions are done in TCP while all audiotransmission is sent through a separate UDP/RTP socket (using the API from JRTPLIB).
So the IP is known from the TCP connection, and the port number of the RTP socket can be sent after connection is established.
The problem is that in TCP only the server needs to do port forwarding for communications to work both ways since you establish a connection, while in UDP you'd have to use recvfrom() -- which afaik needs the ports to be opened in the first place on the client side, which I do not want (and is not needed if you look at any multiplayer game or VoIP client)
Reading on sources that talk about UDP Hole Punching (for example http://en.wikipedia.org/wiki/UDP_hole_punching) for example they keep mentioning starting a udp conversation with the server. That's the thing - how do you actually start a udp conversation(both ways) with the server without the client having to open any ports? in TCP as I mentioned you just need to connect() to the server and communication is possible both ways.
Also -- I know RTP builds on UDP but is there anything else I should know about the RTP hole punching (again, using JRTPLIB) that makes it differ from UDP?
Thanks in advance!
回答1:
There are two possible definitions of "opening a port". One is opening a port with bind() for UDP or listen() for TCP, another one is opening a port in a firewall.
You need to open a port with an API call in order to receive something, there is no way around it, but you probably realize this, so I think you mean opening a port in a firewall. But you don't need to do this on the side that initiates communication (the client). This applies both to TCP and UDP, unless your firewall is set up in a very paranoid mode. Any reasonable firewall would allow a response from a server to a UDP port if there was a datagram sent from this port to the same server some time before. You only need hole punching if both sides are behind NATing firewalls/routers. That's how Skype does it.
Moreover, you don't even have to bother with recvfrom() and such stuff. You can just bind() a UDP socket, then use connect() and recv()/send() or read()/write() exactly in the same way as you'd do with TCP.
来源:https://stackoverflow.com/questions/4634780/c-hole-punching-udprtp