简体   繁体   English

是否可以使用Boost.asio端点来识别UDP连接的客户端?

[英]Can a Boost.asio endpoint be used to identify a client over time for UDP connections?

In a client/server application, my client connects to the server via UDP using Boost.asio . 在客户端/服务器应用程序中,我的客户端使用Boost.asio通过UDP连接到服务器。

The server opens its socket like this: 服务器打开它的套接字如下:

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

The client opens its socket like this: 客户端打开它的套接字如下:

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

Then when a client sends its first message to the server, the server uses the client endpoint as an identifier for future messages. 然后,当客户端将其第一条消息发送到服务器时,服务器将客户端端点用作未来消息的标识符。 Here is 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 the beginning to the end of its work, is it safe for the server to use the endpoint as an identifier of the client? 由于客户端从工作的开始到结束使用相同的套接字实例,因此服务器使用端点作为客户端的标识符是否安全?

A boost IP endpoint at least identifies 3 of the 5 values that uniquely identify a UDP connection: protocol (UDP) , source IP , source port . 升压IP端点至少识别唯一标识UDP连接的5个值中的3个: protocol (UDP)source IPsource port If your server uses only one dest IP / dest port or you add these parameters yourself or this does not matter, then yes you can use this as some sort of session identifier. 如果您的服务器只使用一个dest IP / dest port或者您自己添加这些参数,或者这无关紧要,那么您可以将其用作某种会话标识符。 A few gotchas though: 但有几点困难:

  • This is only realistic during some application-specific transaction. 这在某些特定于应用程序的事务期间是现实的。 For example, in a file transfer client, it might be that you setup a new connection for every file. 例如,在文件传输客户端中,可能是您为每个文件设置了新连接。 Also, a single client might use parallel connections to speed things up making your life harder. 此外,单个客户端可能会使用并行连接来加快速度,从而使您的生活更加艰难。 This is not even UDP specific, TCP has the same issue. 这甚至不是UDP特定的,TCP也有同样的问题。
  • Deleting the session/identifier is extremely hard. 删除会话/标识符非常困难。 UDP has no explicit disconnect as TCP has, so you have to use some idle timeout. UDP没有明确的断开连接,因此您必须使用一些空闲超时。 However, put this too short and you might remove the identifier to soon, put this too long and an actually new connection might be identified as an old one. 但是,这个太短了,你可能很快就删除了标识符,把它放得太长,实际上新的连接可能被识别为连接。

In general, establishing a session concept is usually better done on application level, eg generate a random UUID4 and prefix that to every packet. 通常,建立会话概念通常最好在应用程序级别上完成,例如生成随机UUID4并为每个数据包添加前缀。 Problem one is solved by specifying that the client must reuse this identifier. 通过指定客户端必须重用此标识符来解决问题1。 Problem two is solved because it's unlikely that any client will ever use the same UUID, so you can actually use quite a large timeout. 问题二解决了,因为任何客户端都不可能使用相同的UUID,因此您实际上可以使用相当大的超时。

This depends on your client application. 这取决于您的客户端应用程序。 It needs to open a port locally and send a datagram to your server. 它需要在本地打开一个端口并将数据报发送到您的服务器。 The client can either bind to a specific local port or let the operating system choose a free local port at random. 客户端可以绑定到特定的本地端口,也可以让操作系统随机选择一个空闲的本地端口。 As long as the socket is bound to the local UDP port, the port number won't change. 只要套接字绑定到本地UDP端口,端口号就不会改变。 However, if the client chooses to close the socket after sending a datagram and if it does not explicitly bind to the same local port for the next datagram it is about to send, the operating system is free to choose a totally different port. 但是,如果客户端选择在发送数据报后关闭套接字,并且如果它没有显式绑定到它要发送的下一个数据报的同一本地端口,则操作系统可以自由选择完全不同的端口。

When the client is behind a router with NAT, it might also happen that the source port is rewritten and there is no guarantee that this port number will stay stable for any amount of time. 当客户端位于具有NAT的路由器后面时,可能还会发生源端口被重写,并且无法保证此端口号在任何时间内都能保持稳定。

So while it might work most of the time, I would not rely on the behavior outside a controlled environment. 因此,虽然它可能在大多数时间都有效,但我不会依赖受控环境之外的行为。 You might switch to a connection based protocol (TCP) or use own session IDs. 您可以切换到基于连接的协议(TCP)或使用自己的会话ID。 The latter might be tricky, because you'll need to manage them possibly even across program restarts to prevent double IDs and add some checks to prevent session hijacking if that's an issue for you. 后者可能很棘手,因为您甚至需要在程序重启期间管理它们以防止双ID并添加一些检查以防止会话劫持(如果这对您来说是个问题)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM