5

简而言之,我的问题是,如果您有一个只有一个活动连接的 tcp 服务器,您是否可以只创建一个服务器端数据套接字。在所有教程中,我看到创建了一个新套接字,但我不明白为什么会这样。为什么不创建一个服务器端套接字,然后打开、关闭、重置它(我最初希望 async_accept 以某种方式做到了)?

更详细地说:

我已经完成了异步日间服务器的 boost asio 教程,并且可以让它编译和工作。我什至可以为我的应用程序修改它并让它按照我的意愿运行:)。但是,我原来的方法没有用,我不明白为什么我希望你能帮上忙。

基本上,我想创建一个 TCP 服务器,它只接受一个 TCP 客户端并忽略所有其他客户端,除非第一个客户端断开连接。我使用acceptor.close() 和acceptor.open() 做到了这一点,这样当第一个连接被接受时,我就关闭了acceptor,然后每当我发现一个eof 错误时,我就重新打开了acceptor 来监听新的连接。我天真地认为,因为我只想要一个活动连接,我只需要创建一个:

boost::asio::ip::tcp::socket socket_

因为我只有一个数据套接字从客户端接收数据,所以按照教程创建一个完整的 tcp_connection 类似乎有点过头了,据我所知,它只返回了一个用 io_service 构造的新套接字。(在本教程中,我认为每次服务器接受新连接时,都会使用此代码创建一个新套接字):

class tcp_connection
  : public boost::enable_shared_from_this<tcp_connection>
{
 public:
  typedef boost::shared_ptr<tcp_connection> pointer;

  static pointer create(boost::asio::io_service& io_service)
  {
    return pointer(new tcp_connection(io_service));
  }

  tcp::socket& socket()
  {
    return socket_;
  }


 private:
  tcp_connection(boost::asio::io_service& io_service)
    : socket_(io_service)
  {
  }

  tcp::socket socket_;
  std::string message_;
};

因此,我尝试只使用一个 boost::asio::ip::tcp::socket。我在我的服务器类的构造函数中使用 io_service 以与上面的教程类似的方式对其进行了初始化。我的测试表明我的第一个客户端会连接,只有在第一个客户端断开连接后,第二个客户端才会连接。但是,无论我做了什么, async_accept(socket_,.....) 调用上的数据缓冲区永远不会被填满。最初我只是不断收到 eof 错误,然后我尝试关闭 socked 并重新打开它删除了 eof 错误并给出了传输端未连接错误。显然我在这里做了一些非常愚蠢的事情,但我看不出从哲学上讲我正在尝试做的事情有什么问题。当我使用教程技术创建一个新套接字时,一切都按预期工作。

所以我的问题是我可以只有一个套接字并执行取消、关闭、打开之类的操作吗?我是要绑定还是其他什么,但那不是 async_accept 工作吗?

我现在只使用了一周的 boost asio,这是我第一次在这样的论坛上发帖,所以对我来说放轻松;)。

4

1 回答 1

3

你可以,但你不能。

没有理由不能像您所说的那样实现 TCP,但我所知道的操作系统都没有这样做。

原因很简单,因为操作系统必须支持多个并发连接,因此这是决定实现的设计要求。要实现“只能有一个”的情况,只需在成功接受新连接后关闭侦听器套接字,稍后再重新打开即可。通常不值得为此付出努力。

您描述的开销很小,不值得尝试优化。

于 2012-10-19T18:37:57.180 回答