我正在使用boost::asio::socket
实现RTMP协议。我应该使用阻塞还是异步boost :: asio :: socket读/写来实现协议握手
在async_accept之后,协议需要3步握手。请参见下面的代码:
.
.
.
void RtmpServer::StartAsyncAccept()
{
// Create a new connection
nextConn = RtmpConnection::Create(this, ios);
// FIXME: shall we use async or blocking accept???
acceptor.async_accept
(
nextConn->GetSocket(),
boost::bind
(
&RtmpServer::HandleAsyncAccept,
this,
boost::asio::placeholders::error
)
);
}
.
.
.
void RtmpServer::HandleAsyncAccept(const boost::system::error_code& ec)
{
if (!ec)
{
if (nextConn->StartHandshake())
{
// Push the current connection to the queue
AddConnection(nextConn);
boost::array<char, 0> dummyBuffer;
nextConn->GetSocket().async_read_some
(
// TODO: use a strand for thread-safety.
boost::asio::buffer(dummyBuffer), // FIXME: Why boost::asio::null_buffers() not working?
boost::bind
(
&RtmpConnection::HandleData,
nextConn,
boost::asio::placeholders::error
)
);
}
}
// Start to accept the next connection
StartAsyncAccept();
}
的RtmpConnection::StartHandshake
如果将握手成功(当时RtmpConnection :: HandleData将被调用)返回true,否则为false(连接中断,没有处理还)。
握手有3个主要步骤,每个握手包括Cx和Sx消息,即C{0,1,2}
,S{0,1,2}
。
基本握手必须遵循:
// HANDSHAKE PROTOCOL
// Handshake Sequence:
// The handshake begins with the client sending the C0 and C1 chunks.
//
// The client MUST wait until S1 has been received before sending C2.
// The client MUST wait until S2 has been received before sending any
// other data.
//
// The server MUST wait until C0 has been received before sending S0 and
// S1, and MAY wait until after C1 as well. The server MUST wait until
// C1 has been received before sending S2. The server MUST wait until C2
// has been received before sending any other data.
正如你可能已经注意到,(像往常一样),握手需要等待。例如,
在发送S0之前,服务器必须等待util C0已经收到。在我们的例子中,C0只包含一个单字节版本的整数,服务器必须验证版本是否有效,然后将S0发送给客户端。
等等,类似于C1/S1,C2/S2(但略有不同)。
我的问题是,我应该使用阻塞读/写进行握手,还是异步?
目前我正在使用阻止读/写,这更容易实现。
然而,我搜索了很多,发现很多人建议异步读/写,因为他们有更好的性能和更多的灵活性。
我在问,如果我想用异步套接字读/写来实现它,我该怎么办?我应该为这3个主要步骤创建一堆处理程序吗?或任何其他更好的建议。
示例伪代码将不胜感激。
感谢您的回复。当然,我必须使用(1),因为我的服务器预计会同时接受100多个连接。每个连接一个线程不能很好地扩展。如果我切换到异步,那么您写的示例代码就是我正在做的事情,但正如您所说,实现起来非常繁琐,将会有很多处理程序,因为握手需要3个步骤。顺便说一句,你能介绍我有关状态机的更多信息,以及如何实现一个读/写回调?谢谢。 –
您可以看看libtorrent中的对等连接对象。 http://libtorrent.svn.sourceforge.net/viewvc/libtorrent/trunk/src/bt_peer_connection.cpp?revision=5948&view=markup请注意,在这里asio上面有点抽象。有发送/接收缓冲区和基本连接对象,用于处理重新启动异步读取和写入操作。由于速率限制支持,代码也有点复杂,即有时它不读或写,因为连接超出了带宽配额。 – Arvid