Boost.Asio datagram (UDP) socket that is both bound and connected - c++

I have problems understanding the concept behind Boost.Asio's (using v1.49.0) boost::asio::ip::udp::socket sockets.
First I am gonna to to explain what I want to achieve:
I hide the Boost.Asio sockets behind a very simple interface (Pure Abstract Base Class), so I have two wrapper classes that allow to access either a stream socket or a datagram socket.
I want to configure both the local endpoint and the remote endpoint before passing the Boost.Asio socket to the constructor of my wrapper class.
I want to use the socket.receive (alternatively boost::asio::read) and socket.send (alternatively boost::asio::write) member functions instead of the socket.receive_from and socket.send_to member functions.
The only way to use socket.send and socket.receive with a boost::asio::ip::udp::socket seems to connect the socket.
A UDP socket can both be bound and connected:
Binding is achieved via the socket.bind member function.
Connecting is achieved via the socket.connect member function.
The problem is, that even though I am able to
Open the socket,
Set socket options,
Bind the socket,
Connect the socket,
and to be able to send data via the socket, I can not receive data from the socket. If I don't connect the socket, I can receive data via the bound local endpoint, but I am unable to send data with the approached described.
So my central question is: Am I trying something that is impossible to achieve?
Can I only use bind or connect with one socket instance?
If the answer to the two previous questions is no: What do I have to do, to be able to receive and send data via a bound and connected Boost.Asio UDP socket.
I know that UDP is in fact connectionless, therefore the text uses Boost.Asio terminology. I have also read connect on "connection less" boost::asio::ip::udp::socket which seems to indicate that it is impossible what I am trying.

You are missing one point from man page ofconnect:
If the socket sockfd is of type SOCK_DGRAM, then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.
This means, that if you want to connect the socket, then it will be able to receive datagrams only from remote endpoint (the connected one), i.e. peer will have to bind own socket before sending datagram to your socket waiting for data.
If you need to received data from more than one peer, you can connect udp socket to "any" address (i.e. 0.0.0.0 - udp::v4()) and some port.

Related

Connect a UDP socket, but still receive datagrams from other sources

Is it possible to set the default destination of a UDP socket just like connect does, but without loosing the ability to receive datagrams from other sources?
I'm talking about the native OS socket API (BSD-socket / winsock2) and I'm interested in answers for both linux and windows platforms.
[EDIT:]
In case this is unclear, here is the problematic part from the connect docs:
If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.
Is it possible to set the default destination of a UDP socket just
like connect does, but without loosing the ability to receive packages from other sources?
As far as I can tell, it is not -- connect() on a UDP socket both sets a default-send-destination and installs a filter so that incoming UDP packets from all other destinations than the specified address/port are dropped.
My solution to the problem was to just call sendto() and recvfrom() instead (if you have a UDPSocket class or similar in your codebase, you can cache the default-send address as a private member variable in that class, so that the rest of your codebase can just call a Send() method, and leave it to that method to handle the sendto() arguments)

Winsock ~ Creating an UDP Listener (Multiple vs 1 socket)

Dear Stackoverflowers,
I am researching networking a bit and I decided I'd like to create a small and simple networking library with Winsock. (I am using Completion Ports and Overlapped IO though)
As I researched a bit I came to the following steps for a TCP Listener(Correct me if I am wrong):
Create a Listening Socket
Bind it to a port/IP
Listen on it
When a new connection is created, give a seperate Socket for that connection.
Listener continue's to listen, the specific connection is handled as needed.
EDIT: With a 'connection' from here I mean communication between the server and distinct clients.
Though for an UDP Listener we need to make use of WSARecvFrom which returns the IP address at the lpFrom parameter. Now I was wondering the following:
Is it better to make one UDP Socket listen to incoming connections on a specific port with WSARecvFrom and create new sockets for every specific connection? Or could I just use the UDP Socket itself with WSASendTo. Would that cause any performance penalties if one UDP Socket is used for for example 1000 connections? Or would it be the same or even better then creating/duplicating seperate Sockets for each different incoming connection?
Note: If multiple sockets are needed how would you handle sockets listening on the same port or could a client accept UDP from different ports?
Hope you guys can help!
Ps. Extra tips are always welcome!
Unlike TCP, UDP is connection-less, and as such you don't need to create separate sockets for each party. One UDP socket can handle everything. Bind it to a local IP/Port and call WSARecvFrom() once, and when it reports data to your IOCP you can process the data as needed (if another thread if needed) and then call WSARecvFrom() again. Each time new data arrives, you have to look at the reported lpFrom address to know the IP/Port of the sender. And yes, you can use the same UDP socket for sending data to each sender when needed.

How many sockets are needed per connection?

Say we have a server program with socket sa and new_socket. The tutorial I'm using takes socket sa and new_socket, and two structures of sockaddr_in named server and client; then binds the socket to an IP address:port, then calls listen() function. When listen returns, the program calls
new_socket = accept(sa, (struct sockaddr*)&client, &length);
My question is, lets say there are 3 people connecting...
Do I need to have 3 different structs and 3 different new_sockets for each accept function, say if i want my server to serve 3 different clients connecting to it?
Also, why do we need a new_socket for accept? Why is there two different sockets 1 for bind and 1 for accept? Shouldn't socket operations be performed on the binded one?
I'm trying to implement a class for sockets to make it easier on me, and as a good way to practice my oop skills....
You need one socket for the server in general. This socket is where you set the port that the server is listening on, and call accept() to wait for incoming connections.
In addition, you need a socket for each client connection. This is a new socket that is returned by accept(). This is necessary because a server can handle multiple clients. If you used one socket for everything, there would be no way to tell which client was sending you a message, or indicate which client to send a reply to.

Cpp server, UDP socket for each client

When I'm trying to bind a UDP socket on a specific ip (other than 127.0.0.1/INADDR_LOOPBACK or 0.0.0.0/INADDR_ANY) it fails.
I need to have a dedicated UDP socket for each client (point to point connection).
If I don't bind the socket and use sendto and recvfrom function, the data never arrives.
Any obvious solution ?
You can't bind UDP sockets to nonlocal addresses -- binding a UDP socket to an address means that you want packets that are directed to that address, not ones that are being sent from that address. You'll need to figure out some way to share a single socket across all clients.

Problem using Connect(), send(), recv, with UDP sockets

For my Uni assignment I have to create a fast action paced networked game and so have chosen to use UDP as opposed to TCP. I am aware of a lot of the differences in programming both UDP and TCP and have read through most of the relevant parts of MSDN's documentation on winsock. On MSDN it states that creating a UDP socket via the connect() function should bind the socket to the address and port specified and as a result be able use the send() and recv() functions with the created socket.
For my application I create a client and use connect() using the loopback address which sends a number of packets via the send() function. The client, after calling select(), then receives the packets it sent out. However the result I get from the recv() function is SOCKET_ERROR and the error description using WSAGetLastError() is "An existing connection was forcibly closed by the remote host".
If i use the bind() function and use sendto() to send data over the loopback address, I recv() packets without any errors... Does anyone know why the connect() function is not doing what it is supposed to do, and has anyone been able to use UDP sockets with the connect() function?
You will need to call bind() if you want your program to receive UDP packets. connect() only sets the address that the socket will send packets to if you call send(); it does not associate the socket with a local UDP port to receive on; for that you must call bind().
"UNIX Network Programming" points out that a connect call made on a UDP client side socket figures out and stores all the state about the destination socket address in advance (masking, selecting interface, etc.), saving the cost of doing so on every ::sendto call. This book claims that ::send vs ::sendto can be up to 3x faster because of this reduced overhead - data can go straight to the NIC driver bypassing most IP stack processing. High performance game programmer's may want to consider this.
you should check Beej's Guide to Network Programming Using Internet Sockets, there are nice examples that address your question.
Keep in mind that the UDP protocol is a "connectionless" protocol meaning that you never ever connect to the host, you just send out data. So you can see that connect as an action is meaningless for UDP.
For UDP you should use sendto() and recvfrom() in these function you specify the address and the buffers and that's about it, everything else that is comfortably handled for you in TCP is gone you have to handle things on your own.
In the MSDN documentation its mentioned that you can in fact somehow use the normal send/recv functions with UDP but why would you when you have separate functions already? Like other commented already connect() for UDP does something else it's not essentially a "connect" operation but a sort of a filter to set up send()/recv() for UDP usage.