3

I saw the official async udp server example from boost doc. There you create a single udp socket, bind it to a local port and do something like this:

socket(ioService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port))

socket.async_receive_from(buffer(data, max_length), senderEndpoint, boost::bind(&Request::HandleReceiveFrom, this,
    boost::asio::placeholders::error,
      boost::asio::placeholders::bytes_transferred));

How can I handle multiple concurrent udp connections from clients, because if I try to create another socket using

socket(ioService, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port))

i get bind errors because I already have a socket bound to the same port.

EDIT I can send clients back responses using a different server source port but they will not recognize the response even though I sent the response back to the same client ip/client destination port.

Sam Miller
  • 23,808
  • 4
  • 67
  • 87
Ghita
  • 4,465
  • 4
  • 42
  • 69
  • 2
    Maybe you should just reuse the existing binding. – Mark Garcia Aug 28 '12 at 08:09
  • @MarkGarcia on the socket created I would also need to give back replies to the client. There are multiple clients that would receive data on the same socket. – Ghita Aug 28 '12 at 08:13
  • UDP does not have any connections. If you want connections, you will have to add a connection protocol layer on top of UDP, eg. with a 'Connection' class for each peer and creating a new instance for each new sender that sends a message. – Martin James Aug 28 '12 at 08:13
  • @MartinJames I use my server as a dns proxy. I want to handle multiple clients, proxy their requests, and give answers back. – Ghita Aug 28 '12 at 08:15
  • If I could use something as a boost asio tcp acceptor (for UDP this time) I would be able to create different udp sockets for different client requests – Ghita Aug 28 '12 at 08:21
  • Do you have a way to get a handle on the 5-tuple (specifically including the client IP/Port) from the socket? – MartyE Aug 28 '12 at 08:52
  • @MartyE every time I receive data on the udp socket I receive the sender boost::asio::ip::udp::endpoint. So I guess I can use this for replaying back to clients by creating a new socket with that endpoint and writing to it. I was just thinking at the scalability of this. – Ghita Aug 28 '12 at 09:02
  • If you need to keep state, then you should also consider keeping state in a `map`. Similar to the answer below. If you do not need to keep state, then don't worry about it. – MartyE Aug 28 '12 at 09:07
  • @MarkGarcia You can post your answer as the question answer as it turned out there was not any other solution. – Ghita Sep 02 '12 at 06:23

3 Answers3

6

UDP is a connectionless transport so the concept of connections is meaningless as far as UDP is concerned.

If you want to send data back to the originator of the message you'll need to keep a copy of the sender_endpoint returned in the async_receive_from callback and pass it back in the async_send_to.

This also assumes that the client is also polling/reading and expecting a reply. It need not listen on the same bound port as the server (you don't need to bind with UDP on the client side).

I recommend you have a read of Beej's guide to network programming to help you understand what's going on under the hood of boost ASIO. Boost ASIO complicates things a lot IMHO.

http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#sendtorecv

hookenz
  • 36,432
  • 45
  • 177
  • 286
1

If your clients send their messages to the same port on your server then the only way to distinguish them is by the remote port or a combination of remote port and remote ip.

You create some sort of mapping from client-id (e.g. pair<remote_ip, remote_port>) to a dispatcher type (e.g map< pair<remote_ip, remote_port>, dispatcher>). This then it's up to you to make it threaded in order to support concurrent requests.

StackedCrooked
  • 34,653
  • 44
  • 154
  • 278
  • So, using boost asio is not necessarily to use the same udp socket that I've received data from a client (that in order to send back data to client). – Ghita Aug 28 '12 at 08:45
  • In theory all that counts is that you send to the right IP and the right port number. However, I never tried to send the data back over a different socket then the one it came from. So I am not 100% sure it will work. Update: actually the client will expect the reply to come back from the same server port as the one it sent to. See also [this answer](http://stackoverflow.com/a/763478/75889). – StackedCrooked Aug 28 '12 at 09:07
  • I can make the mapping remote_ip, remote_port so that to replay to that client, but if I don't use the same source port number when replaying back the client will not recognize my response – Ghita Aug 29 '12 at 16:39
1

As it seems the solution can be to use the same socket for sending back responses to clients. Have a look at this question response: Use same udp socket for async receive/send

Community
  • 1
  • 1
Ghita
  • 4,465
  • 4
  • 42
  • 69