asio-users Mailing List for asio C++ library (Page 4)
Brought to you by:
chris_kohlhoff
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(6) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
|
Feb
|
Mar
(1) |
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(5) |
Oct
(7) |
Nov
(8) |
Dec
(11) |
2006 |
Jan
(11) |
Feb
(14) |
Mar
(8) |
Apr
(3) |
May
(27) |
Jun
(15) |
Jul
(43) |
Aug
(64) |
Sep
(19) |
Oct
(44) |
Nov
(69) |
Dec
(82) |
2007 |
Jan
(79) |
Feb
(153) |
Mar
(169) |
Apr
(148) |
May
(181) |
Jun
(114) |
Jul
(152) |
Aug
(104) |
Sep
(77) |
Oct
(128) |
Nov
(185) |
Dec
(215) |
2008 |
Jan
(100) |
Feb
(116) |
Mar
(115) |
Apr
(74) |
May
(152) |
Jun
(107) |
Jul
(117) |
Aug
(115) |
Sep
(141) |
Oct
(75) |
Nov
(31) |
Dec
(47) |
2009 |
Jan
(51) |
Feb
(65) |
Mar
(54) |
Apr
(60) |
May
(6) |
Jun
(107) |
Jul
(82) |
Aug
(133) |
Sep
(144) |
Oct
(11) |
Nov
(54) |
Dec
(26) |
2010 |
Jan
(30) |
Feb
(17) |
Mar
(93) |
Apr
(47) |
May
(93) |
Jun
(73) |
Jul
(32) |
Aug
(60) |
Sep
(59) |
Oct
(58) |
Nov
(71) |
Dec
(28) |
2011 |
Jan
(58) |
Feb
(65) |
Mar
(38) |
Apr
(83) |
May
(45) |
Jun
(70) |
Jul
(71) |
Aug
(7) |
Sep
(33) |
Oct
(65) |
Nov
(33) |
Dec
(16) |
2012 |
Jan
(13) |
Feb
(32) |
Mar
(30) |
Apr
(67) |
May
(57) |
Jun
(59) |
Jul
(8) |
Aug
(61) |
Sep
(48) |
Oct
(23) |
Nov
(29) |
Dec
(8) |
2013 |
Jan
(37) |
Feb
(20) |
Mar
(11) |
Apr
(11) |
May
(9) |
Jun
(26) |
Jul
(6) |
Aug
(18) |
Sep
(7) |
Oct
(29) |
Nov
(2) |
Dec
(17) |
2014 |
Jan
(11) |
Feb
(12) |
Mar
(6) |
Apr
(26) |
May
(17) |
Jun
(12) |
Jul
(12) |
Aug
|
Sep
(6) |
Oct
(3) |
Nov
|
Dec
(7) |
2015 |
Jan
(3) |
Feb
(3) |
Mar
(7) |
Apr
(23) |
May
|
Jun
(1) |
Jul
(2) |
Aug
(33) |
Sep
(16) |
Oct
(2) |
Nov
(2) |
Dec
(13) |
2016 |
Jan
(7) |
Feb
(22) |
Mar
(11) |
Apr
|
May
(10) |
Jun
(2) |
Jul
(3) |
Aug
(2) |
Sep
(1) |
Oct
(29) |
Nov
(3) |
Dec
(21) |
2017 |
Jan
(4) |
Feb
(31) |
Mar
(8) |
Apr
(4) |
May
(1) |
Jun
(4) |
Jul
(32) |
Aug
(28) |
Sep
(2) |
Oct
(11) |
Nov
(1) |
Dec
|
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(10) |
Oct
|
Nov
(4) |
Dec
(20) |
2019 |
Jan
(3) |
Feb
|
Mar
(1) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2020 |
Jan
(2) |
Feb
(1) |
Mar
|
Apr
(2) |
May
(1) |
Jun
|
Jul
(11) |
Aug
(2) |
Sep
(6) |
Oct
|
Nov
|
Dec
|
2021 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
|
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
(1) |
2022 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
(4) |
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
2023 |
Jan
(3) |
Feb
|
Mar
(5) |
Apr
(3) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(4) |
2024 |
Jan
|
Feb
(3) |
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
(6) |
Sep
|
Oct
|
Nov
|
Dec
|
From: Dmitrij V <dm...@gm...> - 2018-12-29 14:44:38
|
Hello Jeff. I can propose you some steps, which allows to catch unwished behaviour: 1) make sequence of initialization of objects (ctor): - error - context - socket - acceptor 2) make listenning (start_server method) - get endpoint from resolver query (host/port in args ..) - open the endpoint by the acceptor - set option reuseaddress - bind the acceptor - listen the acceptor - run work thread with async_accept I hope it will help you. -- the best regards |
From: Bjorn R. <br...@ma...> - 2018-12-29 11:43:56
|
On 12/28/18 7:30 PM, Vinnie Falco wrote: > Yes! This is exactly the problem! I mean, I understand the quote NOW, > that I have finally figured out how error codes and categories work. > But I suspect that quote above is practically meaningless for an > average user who has never encountered it before, including myself. You would obviously need to read the rest of the blog post that leads to the quoted guidelines, but the guidelines can be applied even without a thorough understanding of error codes and categories -- at the very least it tells you not to worry about error_condition unless you write your own error category. |
From: Jeff A. <je...@p2...> - 2018-12-29 08:02:46
|
Hi, Matt. Thanks for the good suggestions. There's a bit of confusion, I think. First, about TcpConnection. I'm guessing you may have missed that the TcpServer constructor initialises a TcpConnection object. *TcpServer::TcpServer*(boost::asio::io_service& io_service, const int port, const TcpReceiveCallback& callback) : *TcpConnection(io_service, port, callback),* acceptor_(io_service_, boost::asio::ip::tcp::endpoint(tcp::v4(), port)), server_connection_state_(TcpServerNotConnected), server_reconnect_delay_(1) { The class TcpConnection just manages the things that are common between a client pattern (I connect to someone, say something, maybe listen for a response) and a server pattern (I listen for someone, then have a conversation with them). Naming is hard. Sorry for the confusion. I think the types are all easily inferred from the arguments passed in and the constructors I call. It's an imperfect art including enough code but not so much that it distracts. The port is an integer because ports are shorts. You lost me on that point. Indeed, I'd expect the compiler to have flagged that one if I'd found an interface that wanted a string or char*. But probably I'm confused: can you point me to the particular function you are looking at? The actual call to accept doesn't worry about ports so much as it looks at the queue of connection requests on a listening socket, picks the one at the head, and provides a new connected socket. From man (2) accept: The accept() system call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket sockfd is unaffected by this call. Jeff On 28/12/18 23:47, Matt Gruenke wrote: > > The other thing I don’t understand is why you’re accepting an integer > port number, as a constructor parameter of TcpConnection. Now that > I’m looking at the reference docs of async_accept(), I don’t see any > version which initializes an integer port number. You must be going > out of your way to get that? Or are you passing in the same port that > the acceptor is listening on? The former is unnecessary, while the > latter is incorrect. > > > > I would pass the socket you’re modifying with async_accept() to > TcpConnection::TcpConnection(). > > > > Also, please post more complete code snippets, so we don’t have to > play unnecessary guesswork. > > > > > > Matt > > > > > > *From:*Matt Gruenke > *Sent:* Friday, December 28, 2018 17:29 > *To:* 'je...@p2...' <je...@p2...> > *Subject:* RE: [asio-users] accept: asio vs BSD > > > > Some code appears to be missing. In the lambda in > TcpServer::Accept(), you’re calling ReceiveHeader(), although that’s a > member function of TcpConnection. It seems like there should be some > code which constructs a new TcpConnection instance (probably also > adding it to a pool) and calls ReceiveHeader() on it. > > > > > Matt > > > > > > *From:*Jeff Abrahamson [mailto:je...@p2...] > *Sent:* Friday, December 28, 2018 17:14 > *To:* asi...@li... > <mailto:asi...@li...> > *Subject:* [asio-users] accept: asio vs BSD > > > > I'm chasing a strange bug (linux, ubuntu 16.04) in which a server > sometimes complains that it is listening on an invalid socket. > (Sometimes this code runs ok.) What I can see is that it listens, and > before anyone can connect, it thinks it successfully accepted, tries > to read, and hits an error: system:9 bad file descriptor. So I agree > with the error, I just don't understand why the accept succeeds. > > [Note: you can skip the code, the real question is below.] Now what > I'm doing seems straight-forward: I create an io_service object, > construct a class that just holds the necessary objects for > communication, that class calls async_accept(), and when that succeeds > it calls async_read(). This is all happening on a highly quiescent > vm, so I'm pretty sure nothing else is going on behind my back. I've > pared the code down so that it really isn't doing anything other than > this at this point. > > My real question is below the code, but I'm sharing the code pro forma > and in the hopes that, as often happens, in preparing this question > and cleaning extraneous cruft from the code I'll solve my problem > myself and so delete the mail. > > boost::asio::io_service io_service; > TcpServer tcp(io_service, port, [](const string& message) -> > string { ... }); > io_service.run(); > > TcpServer::TcpServer(boost::asio::io_service& io_service, const > int port, > const TcpReceiveCallback& callback) > : TcpConnection(io_service, port, callback), > acceptor_(io_service_, > boost::asio::ip::tcp::endpoint(tcp::v4(), port)), > server_connection_state_(TcpServerNotConnected), > server_reconnect_delay_(1) { > Accept(); > } > > TcpConnection::TcpConnection(boost::asio::io_service& io_service, > const int port, const > TcpReceiveCallback& callback) > : io_service_(io_service), > port_(port), > socket_(io_service_), > dead_(false), > error_count_(0), > scheduler_(io_service), > callback_(callback) {} > > void TcpServer::Accept() { > LOGGABLE; > LOG_INFO << "Accept requested."; > server_connection_state_ = TcpServerAcceptWait; > acceptor_.async_accept(socket_, > [this](boost::system::error_code ec) { > LOGGABLE; > if (ec) { > LOG_WARNING << "TcpServer failed to accept on socket: " > << AsioError(ec) > << " (delay=" << server_reconnect_delay_ > << " seconds)"; > if (server_reconnect_delay_ < 60) { > // Exponential backoff, capped at 64 seconds. > server_reconnect_delay_ *= 2; > } > scheduler_.AddTask("Accept", [this]() { return > Accept(); }, > server_reconnect_delay_, true); > return; > } > server_connection_state_ = TcpServerConnected; > LOG_INFO << "Accepting."; > ReceiveHeader(); > }); > } > > void TcpConnection::ReceiveHeader() { > LOGGABLE; > if (dead_) { > LOG_INFO << "TcpConnection::ReceiveHeader(): but we're dead."; > return; > } > // receive_buffer_.clear(); > boost::asio::async_read( > socket_, boost::asio::buffer(receive_buffer_, kTcpHeaderSize), > boost::asio::transfer_exactly(kTcpHeaderSize), > [this](boost::system::error_code ec, std::size_t > received_length) { > LOGGABLE; > if (ec) { > LOG_WARNING << "Header read error: " << AsioError(ec); > // ... > } > // ... > ReceiveBody(read_length); > }); > } > > I'm sure this bug will fall in the morning. I know well enough that > I've stared at this too long for one day. But my confusion is > augmented by knowing that the accept(2) system call returns a new file > descriptor: > > int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); > > So my hypothesis this afternoon was briefly that asio's async_accept() > must be doing the same thing and that I'm therefore calling read on > the listening socket and not on the new connected socket. That > doesn't quite make sense anyway, because I can see via netstat that no > socket is connected (and I didn't run my utility to connect, and this > is a quiescent vm constructed just for these tests). But this is > bothering me now, because I've also spent a bunch of time reading in > /usr/include/boost/asio/ and I don't find the call to the underlying > system call accept(). > > My question is mostly on this last point: *wtf, where is the connected > fd represented in asio?* > > -- > > Jeff Abrahamson > +33 6 24 40 01 57 > +44 7920 594 255 > https://www.p27.eu/jeff/ > <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.p27.eu%2Fjeff%2F&data=02%7C01%7Cmatthew.gruenke%40jci.com%7C6ff6fe5241de41067cf108d66d11eaef%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636816321066716841&sdata=h2zRyXFLnhpNmTN9dceL%2FTciX%2F5km5bpn8l6Ue8ZUgU%3D&reserved=0> > https://www.transport-nantes.com/ > <https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.transport-nantes.com%2F&data=02%7C01%7Cmatthew.gruenke%40jci.com%7C6ff6fe5241de41067cf108d66d11eaef%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636816321066716841&sdata=BgNiAjn3tA%2FoC3G8pJVocnTiIbOxnmHaeHzob%2F2aYFM%3D&reserved=0> > > > > > _______________________________________________ > asio-users mailing list > asi...@li... > https://lists.sourceforge.net/lists/listinfo/asio-users > _______________________________________________ > Using Asio? List your project at > http://think-async.com/Asio/WhoIsUsingAsio -- Jeff Abrahamson +33 6 24 40 01 57 +44 7920 594 255 https://www.p27.eu/jeff/ https://www.transport-nantes.com/ |
From: Matt G. <mat...@jc...> - 2018-12-28 22:47:34
|
The other thing I don’t understand is why you’re accepting an integer port number, as a constructor parameter of TcpConnection. Now that I’m looking at the reference docs of async_accept(), I don’t see any version which initializes an integer port number. You must be going out of your way to get that? Or are you passing in the same port that the acceptor is listening on? The former is unnecessary, while the latter is incorrect. I would pass the socket you’re modifying with async_accept() to TcpConnection::TcpConnection(). Also, please post more complete code snippets, so we don’t have to play unnecessary guesswork. Matt From: Matt Gruenke Sent: Friday, December 28, 2018 17:29 To: 'je...@p2...' <je...@p2...> Subject: RE: [asio-users] accept: asio vs BSD Some code appears to be missing. In the lambda in TcpServer::Accept(), you’re calling ReceiveHeader(), although that’s a member function of TcpConnection. It seems like there should be some code which constructs a new TcpConnection instance (probably also adding it to a pool) and calls ReceiveHeader() on it. Matt From: Jeff Abrahamson [mailto:je...@p2...] Sent: Friday, December 28, 2018 17:14 To: asi...@li...<mailto:asi...@li...> Subject: [asio-users] accept: asio vs BSD I'm chasing a strange bug (linux, ubuntu 16.04) in which a server sometimes complains that it is listening on an invalid socket. (Sometimes this code runs ok.) What I can see is that it listens, and before anyone can connect, it thinks it successfully accepted, tries to read, and hits an error: system:9 bad file descriptor. So I agree with the error, I just don't understand why the accept succeeds. [Note: you can skip the code, the real question is below.] Now what I'm doing seems straight-forward: I create an io_service object, construct a class that just holds the necessary objects for communication, that class calls async_accept(), and when that succeeds it calls async_read(). This is all happening on a highly quiescent vm, so I'm pretty sure nothing else is going on behind my back. I've pared the code down so that it really isn't doing anything other than this at this point. My real question is below the code, but I'm sharing the code pro forma and in the hopes that, as often happens, in preparing this question and cleaning extraneous cruft from the code I'll solve my problem myself and so delete the mail. boost::asio::io_service io_service; TcpServer tcp(io_service, port, [](const string& message) -> string { ... }); io_service.run(); TcpServer::TcpServer(boost::asio::io_service& io_service, const int port, const TcpReceiveCallback& callback) : TcpConnection(io_service, port, callback), acceptor_(io_service_, boost::asio::ip::tcp::endpoint(tcp::v4(), port)), server_connection_state_(TcpServerNotConnected), server_reconnect_delay_(1) { Accept(); } TcpConnection::TcpConnection(boost::asio::io_service& io_service, const int port, const TcpReceiveCallback& callback) : io_service_(io_service), port_(port), socket_(io_service_), dead_(false), error_count_(0), scheduler_(io_service), callback_(callback) {} void TcpServer::Accept() { LOGGABLE; LOG_INFO << "Accept requested."; server_connection_state_ = TcpServerAcceptWait; acceptor_.async_accept(socket_, [this](boost::system::error_code ec) { LOGGABLE; if (ec) { LOG_WARNING << "TcpServer failed to accept on socket: " << AsioError(ec) << " (delay=" << server_reconnect_delay_ << " seconds)"; if (server_reconnect_delay_ < 60) { // Exponential backoff, capped at 64 seconds. server_reconnect_delay_ *= 2; } scheduler_.AddTask("Accept", [this]() { return Accept(); }, server_reconnect_delay_, true); return; } server_connection_state_ = TcpServerConnected; LOG_INFO << "Accepting."; ReceiveHeader(); }); } void TcpConnection::ReceiveHeader() { LOGGABLE; if (dead_) { LOG_INFO << "TcpConnection::ReceiveHeader(): but we're dead."; return; } // receive_buffer_.clear(); boost::asio::async_read( socket_, boost::asio::buffer(receive_buffer_, kTcpHeaderSize), boost::asio::transfer_exactly(kTcpHeaderSize), [this](boost::system::error_code ec, std::size_t received_length) { LOGGABLE; if (ec) { LOG_WARNING << "Header read error: " << AsioError(ec); // ... } // ... ReceiveBody(read_length); }); } I'm sure this bug will fall in the morning. I know well enough that I've stared at this too long for one day. But my confusion is augmented by knowing that the accept(2) system call returns a new file descriptor: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); So my hypothesis this afternoon was briefly that asio's async_accept() must be doing the same thing and that I'm therefore calling read on the listening socket and not on the new connected socket. That doesn't quite make sense anyway, because I can see via netstat that no socket is connected (and I didn't run my utility to connect, and this is a quiescent vm constructed just for these tests). But this is bothering me now, because I've also spent a bunch of time reading in /usr/include/boost/asio/ and I don't find the call to the underlying system call accept(). My question is mostly on this last point: wtf, where is the connected fd represented in asio? -- Jeff Abrahamson +33 6 24 40 01 57 +44 7920 594 255 https://www.p27.eu/jeff/<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.p27.eu%2Fjeff%2F&data=02%7C01%7Cmatthew.gruenke%40jci.com%7C6ff6fe5241de41067cf108d66d11eaef%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636816321066716841&sdata=h2zRyXFLnhpNmTN9dceL%2FTciX%2F5km5bpn8l6Ue8ZUgU%3D&reserved=0> https://www.transport-nantes.com/<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.transport-nantes.com%2F&data=02%7C01%7Cmatthew.gruenke%40jci.com%7C6ff6fe5241de41067cf108d66d11eaef%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636816321066716841&sdata=BgNiAjn3tA%2FoC3G8pJVocnTiIbOxnmHaeHzob%2F2aYFM%3D&reserved=0> |
From: Jeff A. <je...@p2...> - 2018-12-28 22:14:21
|
I'm chasing a strange bug (linux, ubuntu 16.04) in which a server sometimes complains that it is listening on an invalid socket. (Sometimes this code runs ok.) What I can see is that it listens, and before anyone can connect, it thinks it successfully accepted, tries to read, and hits an error: system:9 bad file descriptor. So I agree with the error, I just don't understand why the accept succeeds. [Note: you can skip the code, the real question is below.] Now what I'm doing seems straight-forward: I create an io_service object, construct a class that just holds the necessary objects for communication, that class calls async_accept(), and when that succeeds it calls async_read(). This is all happening on a highly quiescent vm, so I'm pretty sure nothing else is going on behind my back. I've pared the code down so that it really isn't doing anything other than this at this point. My real question is below the code, but I'm sharing the code pro forma and in the hopes that, as often happens, in preparing this question and cleaning extraneous cruft from the code I'll solve my problem myself and so delete the mail. boost::asio::io_service io_service; TcpServer tcp(io_service, port, [](const string& message) -> string { ... }); io_service.run(); TcpServer::TcpServer(boost::asio::io_service& io_service, const int port, const TcpReceiveCallback& callback) : TcpConnection(io_service, port, callback), acceptor_(io_service_, boost::asio::ip::tcp::endpoint(tcp::v4(), port)), server_connection_state_(TcpServerNotConnected), server_reconnect_delay_(1) { Accept(); } TcpConnection::TcpConnection(boost::asio::io_service& io_service, const int port, const TcpReceiveCallback& callback) : io_service_(io_service), port_(port), socket_(io_service_), dead_(false), error_count_(0), scheduler_(io_service), callback_(callback) {} void TcpServer::Accept() { LOGGABLE; LOG_INFO << "Accept requested."; server_connection_state_ = TcpServerAcceptWait; acceptor_.async_accept(socket_, [this](boost::system::error_code ec) { LOGGABLE; if (ec) { LOG_WARNING << "TcpServer failed to accept on socket: " << AsioError(ec) << " (delay=" << server_reconnect_delay_ << " seconds)"; if (server_reconnect_delay_ < 60) { // Exponential backoff, capped at 64 seconds. server_reconnect_delay_ *= 2; } scheduler_.AddTask("Accept", [this]() { return Accept(); }, server_reconnect_delay_, true); return; } server_connection_state_ = TcpServerConnected; LOG_INFO << "Accepting."; ReceiveHeader(); }); } void TcpConnection::ReceiveHeader() { LOGGABLE; if (dead_) { LOG_INFO << "TcpConnection::ReceiveHeader(): but we're dead."; return; } // receive_buffer_.clear(); boost::asio::async_read( socket_, boost::asio::buffer(receive_buffer_, kTcpHeaderSize), boost::asio::transfer_exactly(kTcpHeaderSize), [this](boost::system::error_code ec, std::size_t received_length) { LOGGABLE; if (ec) { LOG_WARNING << "Header read error: " << AsioError(ec); // ... } // ... ReceiveBody(read_length); }); } I'm sure this bug will fall in the morning. I know well enough that I've stared at this too long for one day. But my confusion is augmented by knowing that the accept(2) system call returns a new file descriptor: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); So my hypothesis this afternoon was briefly that asio's async_accept() must be doing the same thing and that I'm therefore calling read on the listening socket and not on the new connected socket. That doesn't quite make sense anyway, because I can see via netstat that no socket is connected (and I didn't run my utility to connect, and this is a quiescent vm constructed just for these tests). But this is bothering me now, because I've also spent a bunch of time reading in /usr/include/boost/asio/ and I don't find the call to the underlying system call accept(). My question is mostly on this last point: *wtf, where is the connected fd represented in asio?* -- Jeff Abrahamson +33 6 24 40 01 57 +44 7920 594 255 https://www.p27.eu/jeff/ https://www.transport-nantes.com/ |
From: Vinnie F. <vin...@gm...> - 2018-12-28 18:30:25
|
On Fri, Dec 28, 2018 at 10:27 AM Bjorn Reese <br...@ma...> wrote: > >> <quote> > >> Use std::error_code for error propagation. > >> Use std::error_code for comparison within a category. > >> Use std::error_condition for comparison between categories. > >> </quote> > > > Do you find my quote above cryptic? Yes! This is exactly the problem! I mean, I understand the quote NOW, that I have finally figured out how error codes and categories work. But I suspect that quote above is practically meaningless for an average user who has never encountered it before, including myself. Regards |
From: Bjorn R. <br...@ma...> - 2018-12-28 18:25:54
|
On 12/28/18 5:40 PM, Vinnie Falco wrote: > On Fri, Dec 28, 2018 at 8:33 AM Bjorn Reese <br...@ma...> wrote: >>> understand them). The blog posts and tutorials floating around the web >>> can sometimes be a little cryptic with references to "system" errors >>> and that sort of nonsense. >> >> As one of said blog posts succinctly states: >> >> <quote> >> Use std::error_code for error propagation. >> Use std::error_code for comparison within a category. >> Use std::error_condition for comparison between categories. >> </quote> > > I'm not sure if you are quoting this to support my statement or to > provide a counter-example... > > I'll assume you are supporting my statement that most of the blog > posts are cryptic :) Do you find my quote above cryptic? |
From: Vinnie F. <vin...@gm...> - 2018-12-28 16:40:59
|
On Fri, Dec 28, 2018 at 8:33 AM Bjorn Reese <br...@ma...> wrote: > > understand them). The blog posts and tutorials floating around the web > > can sometimes be a little cryptic with references to "system" errors > > and that sort of nonsense. > > As one of said blog posts succinctly states: > > <quote> > Use std::error_code for error propagation. > Use std::error_code for comparison within a category. > Use std::error_condition for comparison between categories. > </quote> I'm not sure if you are quoting this to support my statement or to provide a counter-example... I'll assume you are supporting my statement that most of the blog posts are cryptic :) |
From: Bjorn R. <br...@ma...> - 2018-12-28 16:32:20
|
On 12/28/18 5:17 AM, Vinnie Falco wrote: > understand them). The blog posts and tutorials floating around the web > can sometimes be a little cryptic with references to "system" errors > and that sort of nonsense. > > I find it easiest to explain error_condition as the equivalent of an > "error group." That is, multiple distinct values of error_code can map > to the same error_condition. This allows code which can fail to > concisely provide the exact cause of failure (error_code) while also > allowing the code to determine the general category of error. As one of said blog posts succinctly states: <quote> Use std::error_code for error propagation. Use std::error_code for comparison within a category. Use std::error_condition for comparison between categories. </quote> |
From: Vinnie F. <vin...@gm...> - 2018-12-28 13:50:14
|
On Fri, Dec 28, 2018 at 4:13 AM Matt Gruenke <mat...@jc...> wrote: > else if (error != asio::error::make_error_code( asio::error::operation_aborted ) && Umm........errrrmm.... how do I put this... ...there's no need to call make_error_code, in fact calls to make_error_code should be rare. This function is called for you by the implementation to implicitly convert an error enumeration value to error_code. Your code above could be written as: else if (error != asio::error::operation_aborted && On the bright side, this will save you some typing going forward :) :) :) Regards |
From: Matt G. <mat...@jc...> - 2018-12-28 11:04:32
|
My approach is usually to add special-case handling for specific errors, as needed. Everything else is simply lumped together in a generic case. Generally speaking, I handle errors by resetting the connection state machine. Depending on what protocol you’re implementing, there might be other actions you can take to recover. In case it helps to talk about specifics, here's a snippet of a state machine I wrote to drive libdbus. In this case, the state machine stops if no further op is scheduled. Furthermore, calling OpState::processError() eventually results in the appropriate cleanup and potentially restart. Unfortunately, I can’t post the whole thing. Perhaps it could be improved through the use of error conditions. void Fd::handleOp( OpType type, const boost::system::error_code &error ) { OpState &state = m_state[type]; state.isScheduled = false; if (!error) { // process the waiting data state.processWatches( type ); // queue another op, if needed if (!state.watches.empty()) this->scheduleOp( type ); } else if (error != asio::error::make_error_code( asio::error::operation_aborted ) && error != asio::error::make_error_code( asio::error::shut_down )) { // Fwd connection loss to DBus if (error == asio::error::make_error_code( asio::error::connection_aborted ) || error == asio::error::make_error_code( asio::error::connection_reset ) || error == asio::error::make_error_code( asio::error::broken_pipe )) { state.processError( DBUS_WATCH_HANGUP ); } else state.processError( DBUS_WATCH_ERROR ); } } Matt -----Original Message----- From: Jeff Abrahamson [mailto:je...@p2...] Sent: Thursday, December 27, 2018 15:43 To: asi...@li... Subject: [asio-users] asio and good error handling I've used asio to implement some simple tcp and udp messaging. All's well until there's an error. The asio example code mostly just quits on error, which simplifies examples but isn't great for real life: a single service bounces and everything else decides to bounce, too, as they see a broken connection. I've not found any good examples or guidelines for how to handle different errors, perhaps along the lines of "if you get the this error while reading data, then this is a good action to take". I know this isn't one size fits all, but I also know that I don't want to wait around for less common errors just to figure out what triggered them and how to handle them. Even relatively straight-forward things like connection_refused (ECONNREFUSED) can be a bit sticky: do I always want to close and shutdown the socket or are their cases where that's excessive? Maybe if I'm the client, but if I'm the server I can't reconnect, I'm accepting and talking to an ephemeral port on the client. Thanks for any pointers. ps: After getting over some initial hurdles, I've been quite impressed with asio. Many thanks to the developers. -- Jeff Abrahamson +33 6 24 40 01 57 +44 7920 594 255 https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.p27.eu%2Fjeff%2F&data=02%7C01%7Cmatthew.gruenke%40jci.com%7Cbd17a4e12cd44591693c08d66c3e85ec%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636815413136760272&sdata=wcS5kXvlmRmjM8IYWdefRBXhVMigvhQ3BIEFbQ9PJZw%3D&reserved=0 https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.transport-nantes.com%2F&data=02%7C01%7Cmatthew.gruenke%40jci.com%7Cbd17a4e12cd44591693c08d66c3e85ec%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636815413136760272&sdata=z6tzb9PM%2Fr6LVD9va41TuMRu5DgNzOSg6p1MLma9oDg%3D&reserved=0 _______________________________________________ asio-users mailing list asi...@li...<mailto:asi...@li...> https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.sourceforge.net%2Flists%2Flistinfo%2Fasio-users&data=02%7C01%7Cmatthew.gruenke%40jci.com%7Cbd17a4e12cd44591693c08d66c3e85ec%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636815413136760272&sdata=rBXMBRg%2FcK5riHdPDgw8fBz7B%2B7EK%2F89KEZneyHdR28%3D&reserved=0 _______________________________________________ Using Asio? List your project at https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fthink-async.com%2FAsio%2FWhoIsUsingAsio&data=02%7C01%7Cmatthew.gruenke%40jci.com%7Cbd17a4e12cd44591693c08d66c3e85ec%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636815413136760272&sdata=HHXWCBqP2zQ0AA4ngIwD6uNghjG4C6%2BjcR4uc4jPCoM%3D&reserved=0 |
From: Jeff A. <je...@p2...> - 2018-12-28 10:52:33
|
On 28/12/18 02:58, Vinícius dos Santos Oliveira wrote: > Em qui, 27 de dez de 2018 às 19:01, Jeff Abrahamson <je...@p2... > <mailto:je...@p2...>> escreveu: > > I've not found any good examples or guidelines for how to handle > different errors, [...]. > > Thanks for any pointers. > > > Boost.Asio's core error handling transport is boost::system::error_code. > > There is nothing magical to unwrap out of this abstraction. It is a > 2-tuple with a numerical error code (an enum) and a domain. The first > component is like errno. If you and I try to extend the error types, > we may hit code clash as we try to use the same numerical value for > different error codes. That's why there is the error category which > acts as an error domain. > > However I found hard to grasp the difference between error code and > error condition. The “portable” name sometimes associated as the > difference has given me no hints as to whenever to use each one. The > following posts have enlightening information/examples as to this > other matter (so do pay attention): > > * http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html > * http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-2.html > * http://breese.github.io/2017/05/12/customizing-error-codes.html > > > As to the main point of your question, which is trying to figure it > out which errors can arise out of which operations. That's a harder > question to answer. That's a question that can only be answered if you > narrow it to a specific platform. Once a platform has been chosen, you > can read the platform's manual (e.g. the Linux Programmer's Manual > manpages if you're on Linux) to have the answer. Many errors will only > happen on specific circumstances (e.g. EINTR on Linux's read() will > only happen if a signal is sent to the thread, ...). Thanks very much, Vinícius. Your explanation and the links to Chris' explanations of the intentions of the error support mechanism make things quite a bit clearer. I also understand, through this discussion (thanks Vinnie and others), that even knowing my operating environment (linux) my desire for generalisation and clarity is, notwithstanding, probably excessive. I'll deal with those errors I find and re-read my old network programming texts to remind myself of some others that maybe I've forgotten. Indeed, one of the things that led me to asio was the realisation that the higher level libraries (ZMQ, RabbitMQ, others), which did more, still required me to keep in my head most of the networking fundamentals, but then often made it harder to respond. I'm finding that asio is a good level of abstraction for me and my tasks. > Also, IO errors are open-ended/unbounded and new error types can arise > in the future. For instance, modern file systems are known to employ > compression and you could get an insufficient space error just by > flipping one byte that changes the compression ratio and suddenly > there is no more space even thou you're adding no new bytes to the > filesystem (this error would never happen on FAT32). [...] In passing, that's a very nice example, thanks. > [...] > And last, as for your request for a “general strategies” to adopt on > error handling, I feel this request is more appropriate to a “design > patterns book” than to Boost.Asio documentation. It'll really depend a > lot on your use case and I don't feel it is necessary for Boost.Asio > examples to show any error handling strategy besides showing an error > message and aborting operation. I don't fully agree with you on that point. I understand the desire of library developers to define the scope of their project, and talking about design patterns for using a library leads inextricably into opinion (even if well-founded and interesting opinion when coming from the main developers). It also leads to a perceived feature creep, since, hey, we want to write a good library, and here's this stuff that goes well beyond documentation. At the same time, every serious developer who uses the library (asio in this case) will face the question of what to do in the face of errors or exceptions, and shutting down and giving up, like in life, is usually only appropriate on tasks where we don't care. So there's real value to be added by explaining at a high level how one might use the library effectively and develop really useful and robust software with it. It's unfortunate if each developer has to go through that learning process with the same poor tools and explanations. For example, Chris' blog posts that you linked <http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-2.html> would make some very nice example code <Thanks%20very%20much,+Vin%C3%ADcius.++Your+explanation+and+the+links+to+Chris%27+explanations+of+the+intentions+of+the+error+support+mechanism+make+things+quite+a+bit+clearer.++I+also+understand,%20through%20this%20discussion%20%28thanks%20Vinnie%20and%20others%29,%20that%20even%20knowing%20my%20operating%20environment%20%28linux%29%20my%20desire%20for%20generalisation%20and%20clarity%20is%20notwithstanding%20excessive.%20%20I%27ll%20deal%20with%20those%20errors%20I%20find%20and%20re-read%20my%20old%20network%20programming%20texts%20to%20remind%20myself%20of%20some%20others%20that%20maybe%20I%27ve%20forgotten.,,Indeed,%20one%20of%20the%20things%20that%20led%20me%20to%20asio%20was%20realisation%20that%20the%20higher%20level%20libraries%20%28ZMQ,%20RabbitMQ,%20others%29,%20which%20did%20more,%20still%20required%20me%20to%20keep%20in%20my%20head%20most%20of%20the%20networking%20fundamentals,+but+then+often+made+it+harder+to+respond.++I%27m+finding+that+asio+is+a+good+level+of+abstraction.> on how to handle asio errors, even if only to show how to handle a disconnect or something trivial and common (with the comment that other response strategies are possible, but here's a good way to check for the errors and initiate the response). http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-2.html https://www.boost.org/doc/libs/1_69_0/doc/html/boost_asio/examples/cpp11_examples.html Asio is hardly unique in this preference to limit scope to the point of forcing users each to learn on their own how to use it reliably. -- Jeff Abrahamson +33 6 24 40 01 57 +44 7920 594 255 https://www.p27.eu/jeff/ https://www.transport-nantes.com/ |
From: Dmitrij V <dm...@gm...> - 2018-12-28 08:43:49
|
Vinícius dos Santos Oliveira wrote: > ... http://dbmsmusings.blogspot.com/2018/09/newsql-database-systems-are-failing-to.html Thanks for the link ! There are interesting post about consistency and available. In this moment I am writing my own database. The available is always in priority for me - guaranted by indexing, the consistency guaranted by shared mutex (in this moment I have no joins and internal functions like COUNT, foreign keys..). Sorry for no link to sources, that is closed project... -- the best regards |
From: Vinnie F. <vin...@gm...> - 2018-12-28 04:17:50
|
On Thu, Dec 27, 2018 at 5:59 PM Vinícius dos Santos Oliveira <vin...@gm...> wrote: > However I found hard to grasp the difference between error code and error > condition. The “portable” name sometimes associated as the difference has > given me no hints as to whenever to use each one. This was my experience as well. And it is a shame, because error_code and error_condition are incredibly well-designed (now that I finally understand them). The blog posts and tutorials floating around the web can sometimes be a little cryptic with references to "system" errors and that sort of nonsense. I find it easiest to explain error_condition as the equivalent of an "error group." That is, multiple distinct values of error_code can map to the same error_condition. This allows code which can fail to concisely provide the exact cause of failure (error_code) while also allowing the code to determine the general category of error. For example, in a WebSocket implementation, there are many ways that network input can cause a failure. Examples: * A WebSocket Upgrade request specified HTTP/1.0 (instead of the required HTTP/1.1) * A WebSocket Upgrade request is missing the Host field * A frame was received with an illegal opcode * A control frame had the "fragment" bit set Note that the first 2 error codes above are handshake failures, while the last two are protocol errors. If the caller wants to distinguish between a handshake error or a protocol error (a common use-case) they would need to manually check the error code against the list of all known error codes, and know in which grouping they should be placed. Beast reports these four cases as distinct errors: <https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__websocket__error.html> The error condition system allows specific error codes to be mapped to general error conditions. In the list above there are two conditions. The first is the "handshake failed" condition, while the second is the "protocol error" condition. In Beast this is represented using an error condition enum: <https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__websocket__condition.html> Thanks to the magic (or curse) of argument dependent lookup in the design of error_code, comparisons of error codes against error conditions Just Work. Believe it or not, this compiles and works: boost::system::error_code ec = websocket::error::bad_http_version; BOOST_ASSERT(ec == websocket::condition::handshake_failed); We are actually comparing an error_code initialized from the specific, low-level error, against an error condition which represents a high level, generic grouping of websocket failure modes. That's amazing! The beauty of this wonderfully designed error system is that I can add more error codes that existing users don't know about, and map my error codes to the known conditions, then any user code which compares beast errors against the predefined error conditions will Just Work when one of the new error codes is returned. C++ really deserves a better set of documentation that explains in clear and simple terms how error codes and error conditions work, it took me quite a while to figure out and I hear from other people that they have the same experience. error_code is a little C++ gem waiting to be discovered by the general public. Regards |
From: Vinícius d. S. O. <vin...@gm...> - 2018-12-28 01:59:00
|
Em qui, 27 de dez de 2018 às 19:01, Jeff Abrahamson <je...@p2...> escreveu: > I've not found any good examples or guidelines for how to handle > different errors, perhaps along the lines of "if you get the this error > while reading data, then this is a good action to take". I know this > isn't one size fits all, but I also know that I don't want to wait > around for less common errors just to figure out what triggered them and > how to handle them. Even relatively straight-forward things like > connection_refused (ECONNREFUSED) can be a bit sticky: do I always want > to close and shutdown the socket or are their cases where that's > excessive? Maybe if I'm the client, but if I'm the server I can't > reconnect, I'm accepting and talking to an ephemeral port on the client. > > Thanks for any pointers. > Boost.Asio's core error handling transport is boost::system::error_code. There is nothing magical to unwrap out of this abstraction. It is a 2-tuple with a numerical error code (an enum) and a domain. The first component is like errno. If you and I try to extend the error types, we may hit code clash as we try to use the same numerical value for different error codes. That's why there is the error category which acts as an error domain. However I found hard to grasp the difference between error code and error condition. The “portable” name sometimes associated as the difference has given me no hints as to whenever to use each one. The following posts have enlightening information/examples as to this other matter (so do pay attention): - http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html - http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-2.html - http://breese.github.io/2017/05/12/customizing-error-codes.html As to the main point of your question, which is trying to figure it out which errors can arise out of which operations. That's a harder question to answer. That's a question that can only be answered if you narrow it to a specific platform. Once a platform has been chosen, you can read the platform's manual (e.g. the Linux Programmer's Manual manpages if you're on Linux) to have the answer. Many errors will only happen on specific circumstances (e.g. EINTR on Linux's read() will only happen if a signal is sent to the thread, ...). Also, IO errors are open-ended/unbounded and new error types can arise in the future. For instance, modern file systems are known to employ compression and you could get an insufficient space error just by flipping one byte that changes the compression ratio and suddenly there is no more space even thou you're adding no new bytes to the filesystem (this error would never happen on FAT32). For this reason, Rust developers behind io::ErrorKind gave it special treatment (you can never perform an exhaustive match on them without adding a wildcard match): https://github.com/rust-lang/rust/blob/fb86d604bf65c3becd16180b56267a329cf268d5/src/libstd/io/error.rs#L90 But I witnessed some very intelligent Rust developers, but with not-so-much real-world experience in programming and far too much mathematical background[1] to bias their judgement to unwelcome this decision. They miss the point. IO is just the closest we get to the border between our closed abstractions and an open world and are the region most affected by incomplete modelling. “The means whereby to identify dead forms is Mathematical Law. The means whereby to understand living forms is Analogy.” — O. Spengler “Mathematizing represents a very simple and easy human activity, because it deals with fictitious entities with all particulars included, and we proceed by remembering. [...] Physical or daily-life abstractions differ considerably from mathematical abstractions. [...] In general, physical abstractions, including daily-life abstractions are such that particulars are left out — we proceed by a process of forgetting. In other words, no description or ‘definition’ will ever include all particulars.” — Korzybski “This fact has significant ramifications when considering the availability vs. consistency tradeoff that was purported by the CAP theorem. It is not the case that if we guarantee consistency, we have to give up the guarantee of availability. We never had a guarantee of availability in the first place! Rather, guaranteeing consistency causes a reduction to our already imperfect availability.” — http://dbmsmusings.blogspot.com/2018/09/newsql-database-systems-are-failing-to.html (the last quote/example is a trick that I myself have fallen into) And last, as for your request for a “general strategies” to adopt on error handling, I feel this request is more appropriate to a “design patterns book” than to Boost.Asio documentation. It'll really depend a lot on your use case and I don't feel it is necessary for Boost.Asio examples to show any error handling strategy besides showing an error message and aborting operation. [1] other programmers with “far too much mathematical background” didn't fall for this trap, so “too much mathematics” is not a problem here at all and the problem is something else (maybe a confusion in the orders of abstractions) -- Vinícius dos Santos Oliveira https://vinipsmaker.github.io/ |
From: Jeff A. <je...@p2...> - 2018-12-27 21:46:36
|
Thanks, but I think I must not have been clear. This code will run in production. Seeing in the logs what errors have occurred is important, and I do that. But just as important is for the binary to recover. If it got an error because someone with whom it communicates failed, it should just try again, but not too fast, to reconnect if it can. If it's a network issue, maybe it doesn't need to try to reconnect the socket, just understand that it timed out and to try to retransmit again. I have enough programs running that something will always be having an issue with something. But all the examples I've been finding are, well, examples: they don't provide much help understanding the set of recovery strategies for each of the errors I might receive. I've got enough of my own bugs to keep me going: I'd be very happy not to have to get this working by thinking through every last case. Jeff On 27/12/18 22:32, Dmitrij V wrote: > There are two ways to handle the errors. > > 1) exceptions: > > try { /* ... */ } > catch (const asio::error_code &ec) { > std::cerr << "error: " << ec.message() << std::endl; > } > > 2) and by place: > > error_code ec; > > asio::read(sock, buff, ec); > > if (ec) std::cerr << "error: " << ec.message() << std::endl; > > > If you want detailed error reporting - see class error_code (header > <asio/error_code.hpp>) > and its methods like: value(), category() ... > > PS: For me enough string by error_code::message() (for logs)... > > -- > the best regards > > > _______________________________________________ > asio-users mailing list > asi...@li... > https://lists.sourceforge.net/lists/listinfo/asio-users > _______________________________________________ > Using Asio? List your project at > http://think-async.com/Asio/WhoIsUsingAsio -- Jeff Abrahamson +33 6 24 40 01 57 +44 7920 594 255 https://www.p27.eu/jeff/ https://www.transport-nantes.com/ |
From: Dmitrij V <dm...@gm...> - 2018-12-27 21:32:42
|
There are two ways to handle the errors. 1) exceptions: try { /* ... */ } catch (const asio::error_code &ec) { std::cerr << "error: " << ec.message() << std::endl; } 2) and by place: error_code ec; asio::read(sock, buff, ec); if (ec) std::cerr << "error: " << ec.message() << std::endl; If you want detailed error reporting - see class error_code (header <asio/error_code.hpp>) and its methods like: value(), category() ... PS: For me enough string by error_code::message() (for logs)... -- the best regards |
From: Jeff A. <je...@p2...> - 2018-12-27 20:59:34
|
I've used asio to implement some simple tcp and udp messaging. All's well until there's an error. The asio example code mostly just quits on error, which simplifies examples but isn't great for real life: a single service bounces and everything else decides to bounce, too, as they see a broken connection. I've not found any good examples or guidelines for how to handle different errors, perhaps along the lines of "if you get the this error while reading data, then this is a good action to take". I know this isn't one size fits all, but I also know that I don't want to wait around for less common errors just to figure out what triggered them and how to handle them. Even relatively straight-forward things like connection_refused (ECONNREFUSED) can be a bit sticky: do I always want to close and shutdown the socket or are their cases where that's excessive? Maybe if I'm the client, but if I'm the server I can't reconnect, I'm accepting and talking to an ephemeral port on the client. Thanks for any pointers. ps: After getting over some initial hurdles, I've been quite impressed with asio. Many thanks to the developers. -- Jeff Abrahamson +33 6 24 40 01 57 +44 7920 594 255 https://www.p27.eu/jeff/ https://www.transport-nantes.com/ |
From: Michi H. <mic...@cr...> - 2018-11-30 05:34:46
|
Thanks for the suggestion! I'm using boost 1.58, which explains why I never noticed this function __ It looks like this functionality was added in 1.66. I'll see whether I can switch to that. Thanks again, Michi. On 30/11/18, 12:38, "Vinnie Falco" <vin...@gm...> wrote: After the handshake, submit completion handlers for subsequent operations using bind_handler with the executor of the second io_context. Example: io_context ioc1; tcp::socket sock(ioc1); ... io_context ioc2; sock.async_read_some(buffers, bind_executor(ioc2.get_executor(), [](error_code ec, std::size_t bytes_transferred) { ... } Disclaimer: untested Good luck! |
From: Vinnie F. <vin...@gm...> - 2018-11-30 02:37:34
|
On Thu, Nov 29, 2018 at 5:36 PM Michi Henning via asio-users <asi...@li...> wrote: > However, what I want to do is have the handshake performed by the acceptor thread, > but use a different io_service with its own separate thread to perform all the I/O work After the handshake, submit completion handlers for subsequent operations using bind_handler with the executor of the second io_context. Example: io_context ioc1; tcp::socket sock(ioc1); ... io_context ioc2; sock.async_read_some(buffers, bind_executor(ioc2.get_executor(), [](error_code ec, std::size_t bytes_transferred) { ... } Disclaimer: untested Good luck! |
From: Michi H. <mic...@cr...> - 2018-11-30 01:36:21
|
I had a look at the answer in this thread: https://sourceforge.net/p/asio/mailman/message/3802402/ My situation is similar, but differs slightly. I have an io_service with a single thread that waits for incoming connections on an acceptor instance. Once the connection is established, I call async_handshake() to establish a TLS connection. This works fine, no problem. However, what I want to do is have the handshake performed by the acceptor thread, but use a different io_service with its own separate thread to perform all the I/O work once the handshake is complete. The motivation is CPU affinity, avoid context switches and locking, and avoid having lots of incoming TLS connections delay the I/O for already-established connections. I can’t work out how to do this. The socket embeds the io_service, the ssl stream embeds the socket, and the async_read()/async_write() methods are on the stream, so I can’t see how I can do the handshake in one thread, and transfer all subsequent I/O activity to a different thread once the handshake is complete. Any suggestions for how to achieve this? |
From: bruno r. <br...@gm...> - 2018-11-21 10:36:24
|
Hi all, I am getting the error session id uinitialized when accepting the second request from the same host, the 1st request is doing ok, but the second one error is setting with this error message. As a workaround I setted on context the option SSL_OP_NO_TICKET, and SSL_CTX_set_session_cache_mode(_ctx->native_handle(), SSL_SESS_CACHE_OFF); So now the application is working fine but it is not doing ssl cache. I found on google some post saying "asio does not support ssl-session caching mechanism directly", so I tried to implement a mechanism like that, but I am getting the session id uinitialized when the handle_accept is called. I thought I should do it on handshake, after accept. Any hint ? void transport::SocketServer::do_accept() { if (!this->_acceptor.is_open()) throw Exception("Acceptor is not oppened"); transport::server_connection_ptr connection = boost::make_shared<transport::ServerConnection>(this->_io_service , this->_ctx); this->_acceptor.async_accept(connection->get_socket().lowest_layer() , boost::bind(&SocketServer::handle_accept, shared_from_this(), connection, boost::asio::placeholders::error)); LOG_DEBUG("Accept asynchronous..."); } void transport::SocketServer::handle_accept(transport::server_connection_ptr connection, const boost::system::error_code & error) { if (!error) { LOG_DEBUG("Received a new request."); connection->do_handshake(); } else { LOG_ERROR(boost::format{"Accept Error %s\n"} % error.message()); assert(false); } //Listen again this->do_accept(); } Att |
From: Dmitrij V <dm...@gm...> - 2018-09-17 17:07:38
|
Hi! I have server/client app, and ECDSA ca.pem + key.pem but I'm getting error 'short error' when connect to server. Does anyone know hot to fix it ? -- the best regards |
From: Dmitrij V <dm...@gm...> - 2018-09-15 17:55:18
|
Thanks ! My mistake was in signature of handlers, I had: void handle_read(std::shared_ptr<protocol::packet_t> pkt, std::size_t readed, const asio::error_code& err) I have swapped readed and err and got worked code ! That code was taken from my code with boost::asio ... Sorry for my noise ) 2018-09-15 22:20 GMT+05:00, Igor R <boo...@gm...>: >> socket_.async_read_some( >> asio::buffer(pkt->data(), pkt->size()), >> std::bind( // boost::bind( >> &session_ssl::handle_read, >> shared_from_this(), >> pkt, >> std::placeholders::_2, // asio::placeholders::bytes_transferred, >> std::placeholders::_3 // asio::placeholders::error >> ) >> ); > > It should be placeholders::_1, placeholders::_2 > > > _______________________________________________ > asio-users mailing list > asi...@li... > https://lists.sourceforge.net/lists/listinfo/asio-users > _______________________________________________ > Using Asio? List your project at > http://think-async.com/Asio/WhoIsUsingAsio > |
From: Igor R <boo...@gm...> - 2018-09-15 17:20:42
|
> socket_.async_read_some( > asio::buffer(pkt->data(), pkt->size()), > std::bind( // boost::bind( > &session_ssl::handle_read, > shared_from_this(), > pkt, > std::placeholders::_2, // asio::placeholders::bytes_transferred, > std::placeholders::_3 // asio::placeholders::error > ) > ); It should be placeholders::_1, placeholders::_2 |