how to differentiate if client is using TCP or UDP from server side - c++

I am writing simple client-server program.
Client send some messages to server using UDP or TCP. Server must be able to support both UDP and TCP.
If client, sends message using UDP, sequence of method calls in client is socket(),bind(),sendto(),recvfrom(),close() and that in server is socket(),bind(),sendto(),recvfrom(),close().
If it uses TCP,
sequence of call in server is
socket(),bind(),listen(),accept(),send(),recv(),close().
and that in client is
socket(),bind(),connect(),send(),recv(),close()
In my program, user/client is given choice in the start to select what he want to use UDP or TCP. So, my main problem is how can I know or differentiate in the server side, if the client is sending message using TCP or UDP. If it uses TCP, I must call listen(),accept(),send(),recv()
and if it uses UDP, I don't call listen(),accept() but call sendto() and recvfrom().
So, how can I differentiate/know this in the beginning so that I can make appropriate function calls.
Thanks.

Before the packet reaches you, you don't know whether it's UDP or TCP.
So you want to bind to both UDP and TCP sockets if you expect requests both ways.
Once you did, you just know which way it came by the socket you received the packet through.

When you create the socket, you pass a type - SOCK_STREAM (TCP) or SOCK_DGRAM (UDP)
So the two kinds of traffic will be on two different sockets.

Just as Henry Troup pointed out, an IP socket is defined as
(transport, interface, port).
(UDP, 127.0.0.1, 80) is not the same IP socket as (TCP, 127.0.0.1, 80) , thus you can safely bind to both of them and listen for incoming traffic.

just let the TCP socket listen on port X, and do the UDP connections through port Y

Related

My friend and I are receiving packets from a server in UDP, I am able to receive them but he can't

My friend and I are writing a game in sfml. We wrote both the client and the server in C++. The library we used to handle the networking is SFML. The clients send block update packets to the server and the server sends them to all connected players. This works fine, both my friend and I are able to receive the TCP packets. The problem is with the UDP player position packets. The server receives a UDP packet containing the players x y z (position coordinates) and pitch and yaw(direction the player is looking). Then it sends that information to all other connected clients.(This happens 10 times per second) We put a simple printf() statement to detect whether my friend is even receiving the udp packets but it turns out he was not. And I am obviously receiving the UDP packets since it I am able to see his position.
We thought this was because the server is sending UDP packets to the clients' router's IP but the packet does not contain the local ip of the computer the packet is meant for. Later, we learned that when the server sends a packet to the router, the packet gets sent containing a public ip address and a public port, the router then maps that port to a local ip address and a local port. However this is called port forwarding and requires the routers to be configured.
We just want to know why isn't this a problem with TCP connections?
Why am I able to receive the UDP packets without port forwarding?
Is port forwarding necessary for UDP communication?
We just want to know why isn't this a problem with TCP connections?
Because a connection is bidirectional.
Why am I able to receive the UDP packets without port forwarding?
There could be a lot of possibilities and there's no way we can know without looking much more closely. Here are a few possibilities:
You aren't behind a router that's doing NAT.
The router that does NAT for you isn't between your client and the server.
Your client sent a UDP datagram to the server and your router recognizes the response UDP datagram as a reply to that, creating the effect of having a "UDP connection".
Your client uses UPnP and your router supports UPnP to get port forwarding without special effort.
The server sets the source and destination UDP ports incorrectly and, by luck, it still works in your case. For example, the source and destination ports might happen to be the same or your router's NAT is especially permissive.
The server sets its source IP address incorrectly and this just happens to work in your case either because your router's NAT is more permissive or because the IP address you send to and the IP address the server sends from happen to be the same in your case.
You send a UDP datagram to the server and your friend didn't, thus your datagrams are seen as replies and your friend's aren't.
You can narrow things down if you can dump packets at the server. Seeing a UDP datagram from your friend as seen by the server followed by a UDP datagram from the server to your friend would help narrow things down a lot.
Is port forwarding necessary for UDP communication?
Generally no. If the client sends the first UDP datagram and the server correctly swaps the source and destination ports and the source and destination IP addresses, the UDP reply datagram will usually work.
The client must send UDP to the server first. The server must ensure that the UDP datagram is seen as a reply. That means the server looks at the UDP datagrams it gets from the client and ensures that it responds from the port the client sent UDP to and to the port the client sent UDP from. Similarly, it must send to the IP address the client sent from and send from the IP address the client send to.
Generally, servers offer TCP fallback or some other form of NAT penetration in case things don't "just work".

How to use SOCKS 5 proxy with TIdUDPClient properly

I'm trying to use SOCKS v5 proxy with TIdUDPClient. I'm using C++ Builder 10.3 in Windows x64.
Here is my code so far:
TIdSocksInfo* socksInfo = new TIdSocksInfo();
socksInfo->Host = "ip address of the proxy server";
socksInfo->Port = proxyPort;
socksInfo->Version = svSocks5;
socksInfo->Authentication = saNoAuthentication;
IdUDPClient1->Host = "ip address of my udp server";
IdUDPClient1->Port = port;
IdUDPClient1->TransparentProxy = socksInfo;
IdUDPClient1->Connect();
I can connect to my server perfectly without the proxy.
But, it fails to connect with the proxy, so I sniffed the network with wireshark:
The UDP client sends "0.0.0.0" and 0 as the remote info, instead of sending the host and port I set in the code.
Is there anything I can do to fix this?
TIdUDPClient::Connect() will call TIdSocksInfo::OpenUDP() to send a UDP ASSOCIATION request to a SOCKS v5 proxy. TIdUDPClient passes its Host and Port property values as parameters to OpenUDP().
However, TIdSocksInfo::OpenUDP() ignores these Host and Port values that are passed to it. It is hard-coded to send IP 0.0.0.0 (or ::0 for IPv6) and port 0 to the SOCKS proxy. And this is OK, per the SOCKS v5 spec, RFC 1928:
UDP ASSOCIATE
The UDP ASSOCIATE request is used to establish an association within the UDP relay process to handle UDP datagrams. The DST.ADDR and DST.PORT fields contain the address and port that the client expects to use to send UDP datagrams on for the association. The server MAY use this information to limit access to the association. If the client is not in possesion of the information at the time of the UDP ASSOCIATE, the client MUST use a port number and address of all zeros.
A UDP association terminates when the TCP connection that the UDP ASSOCIATE request arrived on terminates.
In the reply to a UDP ASSOCIATE request, the BND.PORT and BND.ADDR fields indicate the port number/address where the client MUST send UDP request messages to be relayed.
So, in a UDP ASSOCIATION request, the specified Host/Port is the local Host/Port that the client will send outgoing datagrams from, or zeros if it does not know that info yet. This lets the proxy's UDP relay know where datagrams will come from when datagrams are being sent from the client to a target peer, and where to send datagrams to when datagrams are being sent from a target peer to the client. If the requested Host/Port is all zeros, the relay should simply use the Host/Port that sent the request.
The Host/Port specified in a UDP ASSOCIATION request is NOT the target peer Host/Port that datagrams are to be forwarded to, like you are thinking. That target info is specified in the individual datagrams that the client will pass to the proxy for forwarding AFTER the association is created. Unlike TCP, UDP is connection-less, so a client can create a single association and then send datagrams to multiple targets, if it wants to.
There is no connection in UDP, so there is nothing for the proxy to send to the target server while processing a UDP ASSOCIATION request. It is simply setting up the proxy's listening port that will then relay subsequent datagrams between the client and the target server.
When sending datagrams for forwarding afterwards, TIdUDPClient::SendBuffer() will call TIdSocksInfo::SendToUDP(), which is also passed the TIdUDPClient's Host and Port property values. SendUDP() will then send a datagram with that target info to the proxy's relay port:
A UDP-based client MUST send its datagrams to the UDP relay server at the UDP port indicated by BND.PORT in the reply to the UDP ASSOCIATE request. If the selected authentication method provides encapsulation for the purposes of authenticity, integrity, and/or confidentiality, the datagram MUST be encapsulated using the appropriate encapsulation. Each UDP datagram carries a UDP request header with it:
... [request header, containing DST.ADDR and DST.PORT in it] ...
When a UDP relay server decides to relay a UDP datagram, it does so silently, without any notification to the requesting client. Similarly, it will drop datagrams it cannot or will not relay. When a UDP relay server receives a reply datagram from a remote host, it MUST encapsulate that datagram using the above UDP request header, and any authentication-method-dependent encapsulation.
The UDP relay server MUST acquire from the SOCKS server the expected IP address of the client that will send datagrams to the BND.PORT given in the reply to UDP ASSOCIATE. It MUST drop any datagrams arriving from any source IP address other than the one recorded for the particular association.
...
So, whatever problem you are having with communicating with your target server, it is likely not related to TIdUDPClient1::Connect() at all, it is more likely related to TIdUDPClient::SendBuffer() and TIdUDPClient::ReceiveBuffer() instead. Either:
the proxy's UDP relay is ignoring the datagrams that TIdUDPClient is requesting be forwarded to the target server, or it is ignoring the server's replies.
datagrams are getting lost in flight on their way to the target server, or on their way back to the proxy.
If you sniff TIdUDPClient's traffic again and see your actual communication datagrams targeting your server properly, then you are going to have to sniff the traffic on the other side of the proxy to make sure those datagrams are actually being forwarded onward. If they are, then the problem has to be on the network or the server itself. If they are not, then the problem has to be on the proxy itself.

Is it possible to send TCP packet to UDP-only server?

I have a UDP server, but I have no UDP capability on client side. Is there a way to send packet via TCP so that UDP server can receive it normally? UDP server cannot be transformed into TCP server.
Reason for wanting to do this is that I'm using a SOCKS5 proxy that does not support UDP associate capability, but I have to use that proxy.
No. The UDP server cannot complete the 3-way handshake required for TCP. If you have IP-raw sockets, it is actually easier to implement UDP on top. However it seems extremely unlikely that you don't have a UDP-stack.
When you talk about "no UDP capability" do you mean the client has no UDP-stack, or is he just behind some firewall that blocks UDP? In the latter case use a proxy.
No, UDP server will not going to accept TCP packets at all (it's a different protocol, so network stack will never propagate those to the application).
If you have to use SOCKS5 proxy, the only way to connect to the said server is by using another proxy-like application, which will stand beyond SOCKS5, accept TCP connections (initiated by app behind SOCKS5 proxy) and retransmit data as UDP.

Winsock: Listen and recv (differences)

I found this defeinitons of funcion listen and recv in winsock library (TCP/IP stream communication).
The listen function places a socket in a state in which it is listening for an incoming connection.
The recv function receives data from a connected socket or a bound connectionless socket.
Does it mean that if I want to receive data from particular socket I should firstly use listen and then recv? I'm not sure if I understand this correctly.
The functions listen and recv have quite different functionalities and uses.
The listen function is designed to allow a server awaiting the connection of one or more clients to listen on a port for if anyone connects.
The recv function is used on an already established socket to receive data which has been sent from the machine at the other end of that socket.
As it has been mentioned in comments, I shall also mention connect. Connect is the counterpart of listen. It talks to the port which a listening machine is listening on and establishes a socket with that machine.
what the BSD socket and winsock libraries don't really make clear is that from a programmers perspective there are two quite different kinds of socket, a listening socket and an established one.
A server will first need to create a listen socket with which it waits for clients, this socket is not used for actually sending any data, it only exists in order to aid the creation of an established socket. However the listening socket does not become the established socket, when a client connects, the listen socket actually creates a second socket for the data transfer.
The established socket is the kind we recognise and use for most things. It is a socket with machines at both ends, listening and sending to perform data transfer.

SOCKS 5 and UDP (C/C++)

I know that SOCKS 5 supports UDP and I have been over the structure of the packets that are sent/received in negotiating with a SOCKS proxy.
The one thing I am not clear on is the procedure for setting up to register with a proxy to send/receive UDP packets.
Specifically, my biggest question is, "Is the connection to the SOCKS proxy that is used to negotiate a UDP associate relationship still made with TCP/IP?". In other words, "Do you end up using a TCP/IP socket to receive UDP packets routed through a SOCKS proxy?"
I would imagine that, if you used a TCP/IP connection to establish a pathway for UDP communication, you'd kind of be missing the whole point of establishing UDP communications. However, on the other hand, if the negotiation were made using UDP (and resulted in a UDP socket), then how would the relationship be terminated when your application is shutting down and no longer needs the proxy to "remember" you?
I have been all over the net looking for an example...but can't find anything. Any help (especially an example) would be appreciated.
https://www.rfc-editor.org/rfc/rfc1928
"A UDP-based client MUST send its datagrams to the UDP relay server at
the UDP port indicated by BND.PORT in the reply to the UDP ASSOCIATE
request"
but
"UDP association terminates when the TCP connection that the UDP
ASSOCIATE request arrived on terminates."
I actually tried using it once, but failed, because many "socks5" proxy
implementations don't actually support the complete protocol.
So I'd suggest to set up a working test case first (find an app which
would support socks5 udp proxy, and a proxy where it would actually work).
Then any network sniffer would tell you how it really works (if it does).