У меня возникают трудности при реализации простого TCP-сервера. Следующий код взят из примеры boost :: asio, «Http Server 1», чтобы быть точным.
void connection::start() {
socket_.async_read_some(
boost::asio::buffer(buffer_),
boost::bind(
&connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
void connection::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) {
if (!e && bytes_transferred) {
std::cout << " " << bytes_transferred <<"b" << std::endl;
data_.append(buffer_.data(), buffer_.data()+bytes_transferred);
//(1) what here?
socket_.async_read_some(
boost::asio::buffer(buffer_),
boost::bind(
&connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
else// if (e != boost::asio::error::operation_aborted)
{
std::cout << data_ << std::endl;
connection_manager_.stop(shared_from_this());
}
}
В оригинальном коде buffer_
достаточно большой, чтобы сохранить весь запрос. Это не то, что мне нужно. Я изменил размер до 32 байт.
Сервер компилируется и прослушивает порт 80 локального хоста, поэтому я пытаюсь подключиться к нему через свой веб-браузер.
Теперь, если оператор (1) закомментирован, тогда считываются только первые 32 байта запроса, и соединение прерывается. Веб-браузер продолжает ждать ответа, сервер делает .. Я не знаю, что.
Если (1) не закомментировано, тогда весь запрос читается (и добавляется к data_
), но это никогда не останавливается — я должен отменить запрос в своем браузере и только после этого else { }
часть запуска — я вижу мой запрос на стандартный вывод.
Вопрос 1: Как мне обработать большой запрос?
Вопрос 2: Как я должен кэшировать запрос (в настоящее время я добавляю буфер в строку)?
Вопрос 3: Как я могу сказать, что запрос окончен? В HTTP всегда есть ответ, поэтому мой веб-браузер продолжает его ждать и не закрывает соединение, но как мой сервер может узнать, что запрос завершен (и, возможно, закрыть его или ответить «200 OK»)?
Предположим, браузер отправляет вам 1360 байт данных asio
чтобы прочитать некоторые данные в ваш буфер, который, как вы говорите, имеет только 32 байта.
тогда в первый раз, когда вы назовете его, ваш обработчик будет вызван с 32 байтами начала данных. здесь, если вы прокомментируете (1), тогда браузер попытается отправить остальные данные (на самом деле браузер уже отправил их, и он находится в буфере операционной системы, которые ждут, чтобы вы оттуда его посмотрели), и вы, возможно, заблокированы io_service::run
за какое-то чудо !!
если вы раскомментируете (1), когда говорите, что ваш цикл запущен, вы читаете первый блок, затем следующий и другой и … до тех пор, пока данные, отправленные браузером, не закончатся, но после этого, когда вы скажете asio
чтобы прочитать еще какие-то данные, он будет ждать больше данных, которые никогда не поступят из браузера (так как браузер уже отправил свою информацию и ожидает вашего ответа), и когда вы отмените запрос из браузера, он закроет свой сокет и затем ваш Обработчик будет вызван с ошибкой, которая говорит, что я не могу прочитать больше данных, так как соединение закрыто. !!
но то, что вы должны сделать здесь, чтобы это сработало: вы должны научиться HTTP
отформатируйте и, таким образом, узнайте, какие данные отправил вам ваш браузер, и дайте на них хороший ответ, после чего будет продолжено ваше общение с клиентом. в этом случае конец буфера \r\n\r\n
и когда вы видите это, вы не должны больше читать данные, вы должны обработать то, что прочитали до сих пор, а затем отправить ответ в браузер.
Других решений пока нет …