Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you bind() and connect() both ends of a UDP connection

Tags:

c

linux

udp

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.

like image 509
gct Avatar asked Mar 16 '12 16:03

gct


People also ask

What does connect () do on a UDP socket?

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.

Does UDP require connect ()?

Connected vs unconnectedUDP sockets can be "connected" (or "established") or "unconnected".

Can two UDP sockets bind same port?

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.

Can you have a connection over UDP?

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.


2 Answers

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.

like image 172
ximaera Avatar answered Oct 05 '22 07:10

ximaera


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

like image 44
datenwolf Avatar answered Oct 05 '22 09:10

datenwolf