I'm writing a point-to-point message queue system, and it has to be able to operate over UDP. I could arbitrarily pick one side or the other to be the "server" but it doesn't seem quite right since both ends are sending and receiving the same type of data from the other.
Is it possible to bind() and connect() both ends so that they send/receive only from each other? That seems like a nicely symmetric way to do it.
The CONNECT command enables an application to associate a socket with the socket name of a peer. The socket then is considered to be a connected UDP socket. You can call the CONNECT command multiple times with different peer names to change the socket association.
Connected vs unconnectedUDP sockets can be "connected" (or "established") or "unconnected".
Yes, it is also possible to have multiple sockets using a single UDP port. With the caveat that only broadcast & multicast packets are going to be multiplexed, unicast packets will only be delivered to the first socket.
Our connection is as real as any TCP connection, and the steady stream of UDP packets it provides is a suitable starting point for a multiplayer action game. Now that you have your virtual connection over UDP, you can easily setup a client/server relationship for a two player multiplayer game without TCP.
Hello from the distant future which is the year 2018, to the year 2012.
There's, in fact, a reason behind connect()
ing an UDP socket in practice (though blessed POSIX and its implementations don't in theory require you to).
An ordinary UDP socket doesn't know anything about its future destinations, so it performs a route lookup each time sendmsg()
is called.
However, if connect()
is called beforehand with a particular remote receiver's IP and port, the operating system kernel will be able to write down the reference to the route and assign it to the socket, making it significantly faster to send a message if subsequent sendmsg()
calls do not specify a receiver (otherwise the previous setting would be ignored), choosing the default one instead.
Look at the lines 1070
through 1171
:
if (connected) rt = (struct rtable *)sk_dst_check(sk, 0); if (!rt) { [..skip..] rt = ip_route_output_flow(net, fl4, sk); [..skip..] }
Until Linux kernel 4.18, this feature had been mostly limited to the IPv4 address family only. However, since 4.18-rc4 (and hopefully Linux kernel release 4.18 as well), it's fully functional with IPv6 sockets as well.
It may be a source of a serious performance benefit, though it will heavily depend on the OS you're using. At least, if you're using Linux and don't use the socket for multiple remote handlers, you should give it a try.
UDP is connectionless, so there's little sense for the OS in actually making some sort of connection.
In BSD sockets one can do a connect
on a UDP socket, but this basically just sets the default destination address for send
(instead giving explicitly to send_to
).
Bind on a UDP socket tells the OS for which incoming, local interface address to actually accept packets (all packets to other addresses are dropped), regardless the kind of socket.
Upon receiving you must use recvfrom
to identify which source the packet comes from. Note that if you want some sort of authentication, then using just the addresses involved is as insecure as no lock at all. TCP connections can be hijacked and naked UDP literally has IP spoofing written all over its head. You must add some sort of HMAC
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With