ブースト asio に基づいてプロキシ サーバーを作成しています。ブラウザからプロキシ サーバーへの着信接続の受け入れを担当するコードの一部で、完全には理解できない動作に直面しています。
だから - 私は次のコンストラクターでアクセプターオブジェクトを作成しています:
_acceptor(_io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port ), true)
ここで聞き始めます (start_accept):
_new_connection.reset(new connection(*_io_services.front(), _connection_id));
_acceptor.async_accept(_new_connection->get_socket(),
boost::bind(&server::handle_accept, this,
boost::asio::placeholders::error));
および handle_accept
if (!error) {
_new_connection->start();
}
// continue waiting for incoming connections
start_accept();
一般に、着信接続を受け入れるための私のコードは、 HTTP Server 2の例と同じです
この問題は、最初の着信接続が閉じられていない場合にのみ発生し、最初の着信接続が閉じられるまで、2 番目の着信がキューに入れられて保留されます。
この 2 つの回答によると、 boost::asio アクセプターの再開と EOF 後の非同期読み取り
Boost::asio tcp サーバーが起動したばかりのときに「イベント」を起動する方法 (別名 io_service.run() )?
アクセプター オブジェクトはすべての着信接続をキューに追加し、保留中の接続が閉じられなくなるまでそれらを受け入れません。
すべての着信接続をすぐに処理したいので、アクセプターのキューで保留されていないため、これまでのところ解決策が見つかりませんでした。
これを実装する正しい方法は何ですか?
connection->start() 関数
void
connection::start() {
_bsocket.async_read_some(boost::asio::buffer(_bbuffer),
boost::bind(&connection::handle_browser_read_headers,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
));
}
グラフィカルな表現 の更新: asio ログのブースト
@asio|1368460995.389629|0*1|socket@00CCFBE4.async_accept
@asio|1368461003.855113|>1|ec=system:0
@asio|1368461003.855113|1*2|socket@00E26850.async_receive
@asio|1368461003.855113|>2|ec=system:0,bytes_transferred=318
@asio|1368461003.856113|1*3|socket@00CCFBE4.async_accept
@asio|1368461003.856113|<1|
@asio|1368461003.856113|2*4|resolver@00E268D8.async_resolve
@asio|1368461003.856113|<2|
@asio|1368461003.866114|>4|ec=system:0,...
@asio|1368461003.866114|4*5|socket@00E26894.async_connect
@asio|1368461003.868114|<4|
@asio|1368461004.204133|>5|ec=system:0
@asio|1368461004.204133|5*6|socket@00E26894.async_send
@asio|1368461004.204133|<5|
@asio|1368461004.204133|>6|ec=system:0,bytes_transferred=302
@asio|1368461004.204133|6*7|socket@00E26894.async_receive
@asio|1368461004.204133|<6|
@asio|1368461004.613156|>7|ec=system:0,bytes_transferred=16384
@asio|1368461004.613156|7*8|socket@00E26850.async_send
@asio|1368461004.614157|<7|
@asio|1368461004.614157|>8|ec=system:0,bytes_transferred=16384
@asio|1368461004.614157|8*9|socket@00E26894.async_receive
@asio|1368461004.614157|<8|
@asio|1368461004.614157|>9|ec=system:0,bytes_transferred=1946
@asio|1368461004.614157|9*10|socket@00E26850.async_send
@asio|1368461004.614157|<9|
@asio|1368461004.614157|>10|ec=system:0,bytes_transferred=1946
@asio|1368461004.614157|10*11|socket@00E26894.async_receive
@asio|1368461004.614157|<10|
@asio|1368461004.618157|>11|ec=system:0,bytes_transferred=14080
@asio|1368461004.618157|11*12|socket@00E26850.async_send
@asio|1368461004.619157|<11|
@asio|1368461004.619157|>12|ec=system:0,bytes_transferred=14080
@asio|1368461004.619157|12*13|socket@00E26894.async_receive
@asio|1368461004.619157|<12|
@asio|1368461019.248994|>13|ec=asio.misc:2,bytes_transferred=0
@asio|1368461019.248994|13|socket@00E26894.close
@asio|1368461019.248994|13|socket@00E26850.close
@asio|1368461019.248994|<13|
@asio|1368461019.253994|0|resolver@00E268D8.cancel
@asio|1368461019.253994|>3|ec=system:0
@asio|1368461019.253994|3*14|socket@00E32688.async_receive
@asio|1368461019.254994|3*15|socket@00CCFBE4.async_accept
@asio|1368461019.254994|<3|
@asio|1368461019.254994|>14|ec=system:0,bytes_transferred=489
@asio|1368461019.254994|14*16|resolver@00E32710.async_resolve
@asio|1368461019.254994|<14|
@asio|1368461019.281995|>16|ec=system:0,...
@asio|1368461019.281995|16*17|socket@00E326CC.async_connect
@asio|1368461019.282996|<16|
@asio|1368461019.293996|>17|ec=system:0
@asio|1368461019.293996|17*18|socket@00E326CC.async_send
@asio|1368461019.293996|<17|
@asio|1368461019.293996|>18|ec=system:0,bytes_transferred=470
@asio|1368461019.293996|18*19|socket@00E326CC.async_receive
@asio|1368461019.293996|<18|
@asio|1368461019.315997|>19|ec=system:0,bytes_transferred=11001
@asio|1368461019.315997|19*20|socket@00E32688.async_send
@asio|1368461019.349999|<19|
@asio|1368461019.349999|>20|ec=system:0,bytes_transferred=11001
@asio|1368461019.349999|20|socket@00E326CC.close
@asio|1368461019.349999|20|socket@00E32688.close
@asio|1368461019.349999|<20|
@asio|1368461019.349999|0|resolver@00E32710.cancel
アクセプターの動作は、サーバー ソケットからのデータの読み取りに使用している関数に依存することがわかりました。接続クラスは、ブラウザーからデータを読み取り、要求 URL を変更し、ホストに接続して要求を送信し、サーバーから応答を読み取り、それをブラウザーに書き戻します。したがって、サーバー本体を読み取る必要があるときは、この関数を使用します
_ssocket.async_read_some(boost::asio::buffer(_sbuffer),
boost::bind(&connection::handle_server_read_body,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
));
サービス応答ヘッダーで content-length が指定されていない場合、EOF まで読み取ります。async_read_some 関数が呼び出され、ソケットに読み取るデータがない場合、EOF が発生するまで約 15 秒待機します。この 15 秒間のすべての新しい着信接続は、アクセプターによって受け入れられません。
しかし、async_read の別のバリアントを使用している場合 -
boost::asio::async_read(_ssocket, boost::asio::buffer(_sbuffer),
boost::bind(&connection::handle_server_read_body,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
));
着信接続は問題なく受け入れられます。しかし、boost::asio::async_read の動作は少し遅く、大量のデータがソケットから読み取られるのを待っており、そのデータが読み取られるまでハンドラーを呼び出さないため、transfer_at_least を指定すると思いました
boost::asio::async_read(_ssocket, boost::asio::buffer(_sbuffer), boost::asio::transfer_at_least(1),
boost::bind(&connection::handle_server_read_body,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
));
ええ、それは良くなりました-しかし、新しい接続を受け入れる際の問題が返されます:/
async_read_some と boost::asio::async_read の本当の違いは何ですか - 何かがブロックされているように感じます。