2014-10-11 2 views
1

Я пытаюсь изучить ASIO boost, но мне трудно понять его. Я хотел бы сделать базовый макет для сервера, который должен быть масштабируемым и эффективным.Не принимается при обращении с async_accept?

В следующем URL приведен пример, где маленький TCP сервер настроен: http://www.boost.org/doc/libs/1_42_0/doc/html/boost_asio/tutorial/tutdaytime3/src.html

То, что я не понимаю, следующая часть:

void start_accept() 
{ 
tcp_connection::pointer new_connection = 
    tcp_connection::create(acceptor_.io_service()); 

acceptor_.async_accept(new_connection->socket(), 
    boost::bind(&tcp_server::handle_accept, this, new_connection, 
     boost::asio::placeholders::error)); 
} 

void handle_accept(tcp_connection::pointer new_connection, 
    const boost::system::error_code& error) 
{ 
    if (!error) 
    { 
    new_connection->start(); 
    start_accept(); 
    } 
} 

start_accept() в конечном итоге вызывает async_accept(), который вызывает его обработчик, когда он получает данные. И обработчик вызывает start_accept() при выполнении.

Но что произойдет, если клиент попытается соединиться, когда обработчик все еще будет работать? Не правда ли, что запрос не мог быть обработан, потому что async_accept() больше не слушал?

Надеюсь, вы можете указать мне в правильном направлении, если я вижу вещи в неправильной перспективе.

+1

[This] (http://stackoverflow.com/a/15883510/1053968) ответ пытается подчеркнуть различие между государством и операциями, что может быть полезно при обучении Boost.Asio. –

ответ

2

Я думаю, вы заметили, что посты Обработчика нового async_accept операции сразу же после обработки акцепта (new_connection->start()):

void handle_accept(tcp_connection::pointer new_connection, 
    const boost::system::error_code& error) 
{ 
    if (!error) 
    { 
    new_connection->start(); // this posts connection specific asynch operations 
    start_accept();   // THIS POSTS THE ASYNC OPERATION AGAIN 
    } 
} 

Вы спрашиваете, есть ли состояние гонки там (где новый асинхронной принять не в ожидании в тот момент, когда ядро ​​получает соединение).

Нет такой расы, так как ядро ​​приостанавливает события в реализации стека TCP/IP.


В самом деле, посмотрите на традиционные select/poll/epoll подходы, подобным образом, вы не получаете асинхронный сигнал, когда сокет изменяет состояние. Вместо этого вы можете опросить его на свой собственный досуг.

Ядро будет иметь ограничения по времени, размеру и количеству буфера в ожидающих события событиях, поэтому, если вы не сможете обработать события в течение определенного времени, они могут исчезнуть.

До тех пор, пока код userland не имеет прямого контроля над необработанным оборудованием, там никогда не будет условия гонки, так как стек ОС должен будет абстрагировать запросы прерываний на нижнем уровне (иначе вы бы назвали эту ОС ExoKernel).

+0

Я понимаю, что вы имеете в виду! Но я думаю, что вы, возможно, неправильно поняли мой вопрос (возможно, это плохо). На самом деле это не происходит, когда new_connection-> start() выполняется до start_accept(), но это больше похоже на: соединение может быть принято только при вызове async_accept. Но async_accept принимает только 1 правильное соединение? Таким образом, когда обработчик запущен (даже если new_connection-> start() является асинхронным, есть еще небольшая задержка?), Никакое соединение не может быть принято до его завершения, а start_accept() вызывается снова и снова возвращается к async_accept(). –

+0

ПОДОЖДИТЕ! Я снова прочитал ваш ответ, и я полностью понимаю, что вы сейчас имеете в виду. Поэтому операционная система временно сохраняет сетевые сообщения, и в конечном итоге, когда они не будут отправлены из очереди, они будут удалены. Это правильно? Таким образом, небольшая задержка не имеет большого значения до тех пор, пока обработчик не займет много времени. (И поэтому нам, вероятно, нужно обрабатывать большие ответы с помощью нитей?) Как последний вопрос !: У вас есть идеи, как долго в среднем, например, Windows и Linux могут кэшировать их? Это вопрос секунд или миллисекунд? –

+0

@ChristianVeenman И да, весь код в конечном счете работает «последовательно» на любом процессоре. Ни одно из двух событий не происходит точно в одно и то же время в любом случае. Но это нормально. В любом случае, в любом случае, нет двух пакетов в одно и то же время. Существует много уровней буферизации, чтобы заставить его работать. То, что вы хотите, - это минимальная латентность. Это то, что вы получаете. – sehe

Смежные вопросы