diff --git a/README.md b/README.md index fd0565e..85929f5 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,12 @@ int main() Socket s(Domain::IPv4, Type::TCP); s.start("127.0.0.1", 24000); while (true) { - auto peer = s.accept(); - auto msg = peer.recv(15); - std::cout << msg << "\n"; + const auto peer = s.accept(); + const auto msg = peer.recv(15); + std::cout << msg << '\n'; } } catch (std::exception &e) { - std::cerr << e.what() << "\n"; + std::cerr << e.what() << '\n'; } } ``` diff --git a/examples/meson.build b/examples/meson.build index 92c2897..29c94eb 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -1,8 +1,12 @@ progs = [['socket_tcp_server', ['socket_tcp_server.cpp']], ['socket_tcp_client', ['socket_tcp_client.cpp']], - ['socket_unix_udp_server',['socket_unix_udp_server.cpp']], - ['socket_unix_udp_client',['socket_unix_udp_client.cpp']]] + ['socket_unix_udp_server',['socket_unix_udp_server.cpp']], + ['socket_unix_udp_client',['socket_unix_udp_client.cpp']], + ['socket_tcp_mt_server', ['socket_tcp_mt_server.cpp']], + ['socket_tcp_mt_client', ['socket_tcp_mt_client.cpp']], + ['socket_tcp_fork_server', ['socket_tcp_fork_server.cpp']]] foreach p : progs - executable(p[0], p[1], include_directories : inc, link_with : netlib) + executable(p[0], p[1], include_directories : inc, + link_with : netlib, dependencies: [thread_dep]) endforeach diff --git a/examples/socket_tcp_client.cpp b/examples/socket_tcp_client.cpp index 8e67cd4..dd1731a 100644 --- a/examples/socket_tcp_client.cpp +++ b/examples/socket_tcp_client.cpp @@ -12,6 +12,6 @@ int main() s.send("Hello World!"); } catch (std::exception &e) { - std::cerr << e.what() << "\n"; + std::cerr << e.what() << '\n'; } } diff --git a/examples/socket_tcp_fork_server.cpp b/examples/socket_tcp_fork_server.cpp new file mode 100644 index 0000000..1a80a2e --- /dev/null +++ b/examples/socket_tcp_fork_server.cpp @@ -0,0 +1,22 @@ +#include "socket.hpp" +#include + +using namespace net; + +int main() +{ + try { + Socket s(Domain::IPv4, Type::TCP); + s.start("127.0.0.1", 24001); + + while (true) { + const auto peer = s.accept(); + if (!fork()) { + std::cout << peer.recv(10) << '\n'; + return 0; + } + } + } catch (std::exception &e) { + std::cerr << e.what() << '\n'; + } +} diff --git a/examples/socket_tcp_mt_client.cpp b/examples/socket_tcp_mt_client.cpp new file mode 100644 index 0000000..6705d78 --- /dev/null +++ b/examples/socket_tcp_mt_client.cpp @@ -0,0 +1,32 @@ +#include "socket.hpp" +#include +#include +#include + +using namespace net; +using namespace std::chrono_literals; + + +void connect_send() +{ + try { + Socket s(Domain::IPv4, Type::TCP); + std::this_thread::sleep_for(2s); + s.connect("127.0.0.1", 24001); + s.send("123456789"); + } catch (std::exception &e) { + std::cerr << e.what() << '\n'; + } +} + + +int main() +{ + std::vector threads; + for (int i = 0; i < 100; ++i) { + threads.push_back(std::thread(connect_send)); + } + for (auto &t : threads) { + t.join(); + } +} diff --git a/examples/socket_tcp_mt_server.cpp b/examples/socket_tcp_mt_server.cpp new file mode 100644 index 0000000..67e1ed6 --- /dev/null +++ b/examples/socket_tcp_mt_server.cpp @@ -0,0 +1,44 @@ +#include "socket.hpp" +#include +#include +#include +#include + +using namespace net; + +std::mutex m; +std::condition_variable cv; +bool accepted = false; + + +void worker_thread(Socket &s) +{ + try { + const auto peer = s.accept(); + std::unique_lock lock(m); + accepted = true; + lock.unlock(); + cv.notify_one(); + std::cout << peer.recv(10) << '\n'; + } catch (std::exception &e) { + std::cerr << e.what() << '\n'; + } +} + + +int main() +{ + try { + Socket s(Domain::IPv4, Type::TCP); + s.start("127.0.0.1", 24001); + + while (true) { + std::thread(worker_thread, std::ref(s)).detach(); + std::unique_lock lock(m); + cv.wait(lock, [] { return accepted; }); + accepted = false; + } + } catch (std::exception &e) { + std::cerr << e.what() << '\n'; + } +} diff --git a/examples/socket_tcp_server.cpp b/examples/socket_tcp_server.cpp index 0b65b46..ba3e275 100644 --- a/examples/socket_tcp_server.cpp +++ b/examples/socket_tcp_server.cpp @@ -12,10 +12,9 @@ int main() while (1) { const auto peer = s.accept(); const auto msg = peer.recv(15); - std::cout << msg << "\n"; + std::cout << msg << '\n'; } - } catch (std::exception &e) { - std::cerr << e.what() << "\n"; + std::cerr << e.what() << '\n'; } } diff --git a/examples/socket_unix_udp_client.cpp b/examples/socket_unix_udp_client.cpp index 472236d..4935847 100644 --- a/examples/socket_unix_udp_client.cpp +++ b/examples/socket_unix_udp_client.cpp @@ -18,8 +18,6 @@ int main() unixClient.write("hello server"); } catch (std::exception &e) { - std::cout << " Something unexpected happened: " << e.what() << '\n'; + std::cout << e.what() << '\n'; } - - return 0; -} \ No newline at end of file +} diff --git a/examples/socket_unix_udp_server.cpp b/examples/socket_unix_udp_server.cpp index f7ebba7..4dfd22a 100644 --- a/examples/socket_unix_udp_server.cpp +++ b/examples/socket_unix_udp_server.cpp @@ -18,8 +18,6 @@ int main() std::cout << "Some client sent: " << res << '\n'; } catch (std::exception &e) { - std::cout << " Something unexpected happened: " << e.what() << '\n'; + std::cout << e.what() << '\n'; } - - return 0; -} \ No newline at end of file +} diff --git a/include/socket.hpp b/include/socket.hpp index eeef747..422b057 100644 --- a/include/socket.hpp +++ b/include/socket.hpp @@ -26,6 +26,7 @@ class Socket final { int sockfd; Domain sock_domain; Type sock_type; + bool isClosed = false; /** @@ -850,11 +851,11 @@ class Socket final { * @access public * Unlinks the unix socket path. */ - void unlink() const noexcept + bool unlink() const noexcept { - if (sock_domain == Domain::UNIX) { - ::unlink(unix.sun_path); - } + return (sock_domain == Domain::UNIX && !isClosed) + ? ::unlink(unix.sun_path) == 0 + : false; } @@ -863,15 +864,16 @@ class Socket final { * @access public * Closes the Socket for terminating connection. */ - void close() const noexcept { ::close(sockfd); } + bool close() const noexcept + { + return (!isClosed) ? ::close(sockfd) == 0 : false; + } - ~Socket() + ~Socket() noexcept { - if (sock_domain == Domain::UNIX) { - ::unlink(unix.sun_path); - } - ::close(sockfd); + unlink(); + close(); } }; } diff --git a/test/socket_bind_test.cpp b/test/socket_bind_test.cpp index f5e890e..fd3625b 100644 --- a/test/socket_bind_test.cpp +++ b/test/socket_bind_test.cpp @@ -97,6 +97,7 @@ TEST(Socket, Bind) }), std::invalid_argument); + Socket unixSocket(Domain::UNIX, Type::TCP); std::string unixSocketPath("/tmp/unixSocketFile"); unixSocket.bind([&](AddrUnix &s) { @@ -104,9 +105,9 @@ TEST(Socket, Bind) }); AddrUnix actualUnixSocket; socklen_t actualUnixSocketSize = sizeof(actualUnixSocket); - ASSERT_NE(getsockname(unixSocket.getSocket(), - (sockaddr *) &actualUnixSocket, - &actualUnixSocketSize), - -1); + ASSERT_NE( + getsockname(unixSocket.getSocket(), (sockaddr *) &actualUnixSocket, + &actualUnixSocketSize), + -1); EXPECT_EQ(actualUnixSocket.sun_path, unixSocketPath); }