From cff61b8cf4b1f00a317600554f0dc873c498e4f3 Mon Sep 17 00:00:00 2001 From: fpagliughi Date: Fri, 16 Aug 2019 17:31:12 -0400 Subject: [PATCH] Rewrote the multi-threaded client example with a cloned socket. --- examples/tcp/tcpechomt.cpp | 18 +++++------------- include/sockpp/socket.h | 2 +- include/sockpp/stream_socket.h | 15 +++++++++++++++ src/socket.cpp | 2 +- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/examples/tcp/tcpechomt.cpp b/examples/tcp/tcpechomt.cpp index 712c406..d0e5730 100644 --- a/examples/tcp/tcpechomt.cpp +++ b/examples/tcp/tcpechomt.cpp @@ -61,9 +61,6 @@ void read_thr(sockpp::tcp_socket rdSock) if (n < 0) cout << "Read error: " << rdSock.last_error_str() << endl; - - // Reset to prevent double close - rdSock.reset(); } // -------------------------------------------------------------------------- @@ -91,13 +88,10 @@ int main(int argc, char* argv[]) cout << "Created a connection from " << conn.address() << endl; - // We create a read socket that uses the same handle as the connector, - // which we will move into the read thread. We need to be careful to - // reset this socket before it goes out of scope so that it doesn't - // close the underlying handle. + // We create a read thread and send it a clone (dup) of the + // connector socket. - sockpp::tcp_socket rdSock(conn.handle()); - std::thread rdThr(read_thr, std::move(rdSock)); + std::thread rdThr(read_thr, std::move(conn.clone())); // The write loop get user input and writes it to the socket. @@ -112,12 +106,10 @@ int main(int argc, char* argv[]) int ret = !conn ? 1 : 0; // Shutting down the socket will cause the read thread to exit. + // We wait for it to exit before we leave the app. conn.shutdown(SHUT_WR); - - // Now, we make sure the thread is done and the - // read socket is out of scope. - rdThr.join(); + return ret; } diff --git a/include/sockpp/socket.h b/include/sockpp/socket.h index cbadcb6..4813f2f 100644 --- a/include/sockpp/socket.h +++ b/include/sockpp/socket.h @@ -205,7 +205,7 @@ public: * @return A new socket object that refers to the same socket as this * one. */ - socket clone(); + socket clone() const; /** * Clears the error flag for the object. * @param val The value to set the flag, normally zero. diff --git a/include/sockpp/stream_socket.h b/include/sockpp/stream_socket.h index 6f29115..4bce4d0 100644 --- a/include/sockpp/stream_socket.h +++ b/include/sockpp/stream_socket.h @@ -102,6 +102,21 @@ public: base::operator=(std::move(rhs)); return *this; } + /** + * Creates a new stream_socket that refers to this one. + * This creates a new object with an independent lifetime, but refers + * back to this same socket. On most systems, this duplicates the file + * handle using the dup() call. + * A typical use of this is to have separate threads for reading and + * writing the socket. One thread would get the original socket and the + * other would get the cloned one. + * @return A new stream socket object that refers to the same socket as + * this one. + */ + stream_socket clone() const { + auto h = base::clone().release(); + return stream_socket(h); + } /** * Open the socket. * @return @em true on success, @em false on failure. diff --git a/src/socket.cpp b/src/socket.cpp index 5fec722..f2fbdaf 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -110,7 +110,7 @@ void socket::destroy() // -------------------------------------------------------------------------- -socket socket::clone() +socket socket::clone() const { socket_t h = INVALID_SOCKET; #if defined(_WIN32)