Can the Boost.asio endpoint be used to identify the client over time for UDP connections?

In a client-server application, my client connects to the server over UDP using Boost.asio .

The server opens its socket as follows:

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

      

The client opens its socket as follows:

boost::asio::ip::udp::socket socket;
socket( _ioService );
socket.open( boost::asio::ip::udp::v4() );

      

Then, when the client sends its first message to the server, the server uses the client's endpoint as an identifier for future messages. Here's a simplification of the identification process:

class Server
{
private:
  boost::asio::ip::udp::socket socket;
  boost::asio::ip::udp::endpoint receiveEndpoint;

private:
  void waitIncoming()
  {
    socket.async_receive_from
      ( boost::asio::null_buffers(), receiveEndpoint,
        boost::bind( &Server::messageReceived, this ) );
  }

  void messageReceived()
  {
    registerClient( receiveEndpoint );
  }
}

      

Since the client uses the same socket instance from start to finish, is it safe for the server to use the endpoint as the client ID?

+3


source to share


2 answers


A boost Endpoint IP point at least 3 of 5 identifies values that uniquely identify UDP-compound: protocol (UDP)

, source IP

, source port

. If your server only uses one dest IP

/ dest port

or you add these parameters yourself, or it doesn't matter, then yes, you can use that as a kind of session id. Several mistakes:

  • This is realistic for some application-specific transactions. For example, in a file transfer client, it might be stated that you establish a new connection for each file. Plus, one client can use concurrent connections to speed things up, making your life more complex. It's not even UDP, TCP has the same problem.
  • Deleting a session / id is extremely difficult. UDP doesn't have an explicit disable as TCP does, so you need to use some idle timeout. However, this is too short, and you can quickly remove this identifier by adding it too long, and in fact, the new connection may be identified as the old one.


In general, session concept creation is usually better done at the application level, eg. generate random UUID4 and prefix for each package. One issue was addressed by specifying that the client should reuse this identifier. The second problem is solved because it is unlikely that any client will ever use the same UUID, so you can use a rather long timeout.

+1


source


It depends on your client application. It should open the port locally and send a datagram to your server. The client can either bind to a specific local port, or the operating system chooses an arbitrary free local port. As long as the socket is bound to a local UDP port, the port number will not change. However, if the client wants to close the socket after sending the datagram, and if it is not explicitly bound to the same local port for the next datagram it is about to send, the operating system may choose a completely different port.

When the client is behind a NAT router, it can also happen that the original port is overwritten, and there is no guarantee that this port number will remain stable at all times.



So, while it might work most of the time, I won't rely on behavior outside of a controlled environment. You can switch to connection based protocol (TCP) or use your own session IDs. The latter can be tricky because you will need to manage it, perhaps even on program restart, to prevent duplicate ids and add some checks to prevent session hijacking if that's a problem for you.

0


source







All Articles