Sto scrivendo server proxy basato su boost asio. Nella parte del mio codice responsabile dell'accettazione delle connessioni in entrata dal browser al server proxy, sto affrontando il comportamento che non sono completamente comprensibile.boost :: asio :: acceptor - accetta nuove connessioni in entrata mentre quelle vecchie sono ancora aperte
Così - Sto creando oggetto di accettazione con la prossima costruttore:
_acceptor(_io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port), true)
iniziare ad ascoltare qui (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));
e handle_accept
if (!error) {
_new_connection->start();
}
// continue waiting for incoming connections
start_accept();
In generale il mio codice per accettare le connessioni in entrata è lo stesso come nell'esempio HTTP Server 2
Il problema si verifica solo quando la prima connessione in ingresso non è stata chiusa, quindi il secondo in entrata verrà messo in coda e in attesa, fino a quando il primo verrà chiuso.
Secondo questi due risposte: boost::asio acceptor reopen and async read after EOF
How to launch an "event" when my Boost::asio tcp server just start running (AKA io_service.run())?
L'oggetto accettatore aggiungerà tutte le connessioni in entrata nella coda e non accetterà loro fino in attesa di connessione non verrà chiusa.
Voglio ottenere l'elaborazione immediata per tutte le connessioni in ingresso, quindi non sono in attesa nella coda dell'accettatore e non ho trovato alcuna soluzione fino ad ora.
Potrebbe aiutarmi, qual è il modo giusto per implementarlo?
connection-> start() funzione
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
));
}
Graphical representation UPDATE: Boost tronchi ASIO
@asio|1368460995.389629|0*1|[email protected]_accept
@asio|1368461003.855113|>1|ec=system:0
@asio|1368461003.855113|1*2|[email protected]_receive
@asio|1368461003.855113|>2|ec=system:0,bytes_transferred=318
@asio|1368461003.856113|1*3|[email protected]_accept
@asio|1368461003.856113|<1|
@asio|1368461003.856113|2*4|[email protected]_resolve
@asio|1368461003.856113|<2|
@asio|1368461003.866114|>4|ec=system:0,...
@asio|1368461003.866114|4*5|[email protected]_connect
@asio|1368461003.868114|<4|
@asio|1368461004.204133|>5|ec=system:0
@asio|1368461004.204133|5*6|[email protected]_send
@asio|1368461004.204133|<5|
@asio|1368461004.204133|>6|ec=system:0,bytes_transferred=302
@asio|1368461004.204133|6*7|[email protected]_receive
@asio|1368461004.204133|<6|
@asio|1368461004.613156|>7|ec=system:0,bytes_transferred=16384
@asio|1368461004.613156|7*8|[email protected]_send
@asio|1368461004.614157|<7|
@asio|1368461004.614157|>8|ec=system:0,bytes_transferred=16384
@asio|1368461004.614157|8*9|[email protected]_receive
@asio|1368461004.614157|<8|
@asio|1368461004.614157|>9|ec=system:0,bytes_transferred=1946
@asio|1368461004.614157|9*10|[email protected]_send
@asio|1368461004.614157|<9|
@asio|1368461004.614157|>10|ec=system:0,bytes_transferred=1946
@asio|1368461004.614157|10*11|[email protected]_receive
@asio|1368461004.614157|<10|
@asio|1368461004.618157|>11|ec=system:0,bytes_transferred=14080
@asio|1368461004.618157|11*12|[email protected]_send
@asio|1368461004.619157|<11|
@asio|1368461004.619157|>12|ec=system:0,bytes_transferred=14080
@asio|1368461004.619157|12*13|[email protected]_receive
@asio|1368461004.619157|<12|
@asio|1368461019.248994|>13|ec=asio.misc:2,bytes_transferred=0
@asio|1368461019.248994|13|[email protected]
@asio|1368461019.248994|13|[email protected]
@asio|1368461019.248994|<13|
@asio|1368461019.253994|0|[email protected]
@asio|1368461019.253994|>3|ec=system:0
@asio|1368461019.253994|3*14|[email protected]_receive
@asio|1368461019.254994|3*15|[email protected]_accept
@asio|1368461019.254994|<3|
@asio|1368461019.254994|>14|ec=system:0,bytes_transferred=489
@asio|1368461019.254994|14*16|[email protected]_resolve
@asio|1368461019.254994|<14|
@asio|1368461019.281995|>16|ec=system:0,...
@asio|1368461019.281995|16*17|[email protected]_connect
@asio|1368461019.282996|<16|
@asio|1368461019.293996|>17|ec=system:0
@asio|1368461019.293996|17*18|[email protected]_send
@asio|1368461019.293996|<17|
@asio|1368461019.293996|>18|ec=system:0,bytes_transferred=470
@asio|1368461019.293996|18*19|[email protected]_receive
@asio|1368461019.293996|<18|
@asio|1368461019.315997|>19|ec=system:0,bytes_transferred=11001
@asio|1368461019.315997|19*20|[email protected]_send
@asio|1368461019.349999|<19|
@asio|1368461019.349999|>20|ec=system:0,bytes_transferred=11001
@asio|1368461019.349999|20|[email protected]
@asio|1368461019.349999|20|[email protected]
@asio|1368461019.349999|<20|
@asio|1368461019.349999|0|[email protected]
ho scoperto che il comportamento di accettore dipende da funzioni che sto usando per i dati letti dal socket server . la classe di connessione legge i dati dal browser, modifica l'URL della richiesta, si connette all'host e invia la richiesta, quindi legge la risposta dal server e la scrive sul browser. Quindi nel momento in cui ho bisogno di leggere il corpo del server - Io uso questa funzione
_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
));
Se lunghezza del contenuto non è stato specificato nelle intestazioni di risposta di servizio, sto leggendo fino EOF. Se è stata chiamata la funzione async_read_some e non ci sono più dati da leggere sul socket, è in attesa di ~ 15 secondi prima che EOF venga generato. Tutte le nuove connessioni in entrata durante questo 15 sec non saranno accettate dall'accettatore.
Ma se sto usando un'altra variante del 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
));
connessioni in entrata vengono accettate bene.Ma potenzia: asio :: async_read funziona un po 'lento, aspetta che vengano letti dati dal socket e non chiama handler fino a che i dati non saranno letti, quindi - ho pensato di specificare 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
));
Sì, è diventato migliore - ma il problema con l'accettazione di nuove connessioni rendimenti:/
ciò che è reale differenza tra - async_read_some e boost :: ASIO :: async_read - ci si sente come qualcosa è bloccato.
È possibile visualizzare il codice all'interno della funzione start()? Forse sta bloccando il tuo codice, quindi non accetta accept() ing. – Bogolt
Ho una domanda aggiornata. In generale ho controllato questo, non uso alcuna operazione di blocco nella classe di connessione. E dai registri di debug vedo che la funzione server :: start_accept è stata chiamata immediatamente dopo handle_accept. Ma la nuova connessione in qualche modo non è accettata da acceptor. Sarà accettato solo quando il primo verrà chiuso. – miks131
Forse è collegato al comportamento del proxy in qualche modo. Sto usando questo scenario per riprodurre il problema. Sto leggendo la risposta dal server che manca l'intestazione Content-Lenght. quindi sto usando la funzione async_read_some su un socket del server. Se la lunghezza del contenuto non è specificata, sto leggendo finché non verrà restituito EOF. L'ultima chiamata della funzione async_read_some sul socket del server, quando non ci sono più dati da leggere richiede molto tempo ~ 10 sec, se la nuova connessione in arrivo appare da browser a proxy durante quel periodo - non sarà accettata da acceptor. – miks131