use*_*872 5 c++ sockets boost tcp boost-asio
简而言之,我的问题是,如果您有一台只有一个活动连接的 tcp 服务器,您可以只创建一个服务器端数据套接字吗?在所有教程中,我看到创建了一个新套接字,但我不明白为什么会出现这种情况。为什么不创建一个服务器端套接字,然后打开、关闭、重置它(我最初希望 async_accept 以某种方式做到了)?
更详细地说:
我已经完成了异步日间服务器的 boost asio 教程,并且可以让它编译和工作。我什至可以为我的应用程序修改它并让它按照我的意愿运行:)。然而,我原来的方法不起作用,我不明白为什么,这就是我希望得到你的帮助的地方。
基本上我想创建一个 TCP 服务器,它只接受一个 TCP 客户端并忽略所有其他客户端,除非第一个客户端断开连接。我使用acceptor.close()和acceptor.open()来做到这一点,这样当第一个连接被接受时,我只是关闭了接受器,然后每当我发现一个eof错误时,我就重新打开接受器来监听新的连接。我天真地认为,因为我只想要一个活动连接,所以我只需要创建一个:
boost::asio::ip::tcp::socket socket_
Run Code Online (Sandbox Code Playgroud)
由于我只有一个数据套接字从客户端接收数据,因此根据教程创建整个 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_;
};
Run Code Online (Sandbox Code Playgroud)
因此,我尝试只使用一个 boost::asio::ip::tcp::socket。我使用 io_service 以与上面教程类似的方式在服务器类的构造函数中初始化了它。我的测试表明,我的第一个客户端会连接,只有在第一个客户端断开连接后,第二个客户端才会连接。但是,无论我做什么, async_accept(socket_,.....) 调用上的数据缓冲区都永远不会被填满。最初我只是不断收到 eof 错误,然后我尝试关闭 socked 并重新打开,这消除了 eof 错误并给出了传输端未连接错误。显然我在这里做了一些非常愚蠢的事情,但我看不出从哲学上讲我想做的事情有什么问题。当我使用教程技术创建一个新套接字时,一切都按预期工作。
所以我的问题是我可以只有一个套接字并执行诸如取消、关闭、打开之类的操作吗?我是要绑定还是其他东西,但这不是 async_accept 工作吗?
我现在只使用了 boost asio 一周,这是我第一次在这样的论坛上发帖,所以对我要宽容;)。
你可以,但你不能。
没有理由不能像你所说的那样实现 TCP,但据我所知,没有操作系统这样做。
原因很简单,操作系统必须支持多个并发连接,因此这是决定实现的设计要求。要实现“只能有一个”情况,只需在成功接受新连接后关闭侦听器套接字并稍后重新打开它即可。通常不值得为此付出努力。
您描述的开销很小,不值得尝试优化。