From 9c42586bc406015be0145576fd6cb3586686b4ca Mon Sep 17 00:00:00 2001 From: crupest Date: Mon, 7 Jun 2021 23:24:43 +0800 Subject: import(life): ... --- .../computer-network-experiment/CMakeLists.txt | 2 +- works/life/computer-network-experiment/Common.cpp | 8 +-- works/life/computer-network-experiment/Common.h | 5 +- works/life/computer-network-experiment/IO.cpp | 80 ++++++++++++++++++++++ works/life/computer-network-experiment/IO.h | 66 ++++++++++++++++++ works/life/computer-network-experiment/Output.cpp | 76 -------------------- works/life/computer-network-experiment/Output.h | 67 ------------------ works/life/computer-network-experiment/client.cpp | 2 +- works/life/computer-network-experiment/server.cpp | 24 +++++-- 9 files changed, 172 insertions(+), 158 deletions(-) create mode 100644 works/life/computer-network-experiment/IO.cpp create mode 100644 works/life/computer-network-experiment/IO.h delete mode 100644 works/life/computer-network-experiment/Output.cpp delete mode 100644 works/life/computer-network-experiment/Output.h (limited to 'works') diff --git a/works/life/computer-network-experiment/CMakeLists.txt b/works/life/computer-network-experiment/CMakeLists.txt index 4d4277c..09c1ea4 100644 --- a/works/life/computer-network-experiment/CMakeLists.txt +++ b/works/life/computer-network-experiment/CMakeLists.txt @@ -9,7 +9,7 @@ set(CMAKE_CXX_STANDARD 17) find_package(fmt CONFIG REQUIRED) find_package(Microsoft.GSL CONFIG REQUIRED) -add_library(base STATIC Common.cpp StringUtil.cpp Output.cpp) +add_library(base STATIC Common.cpp StringUtil.cpp IO.cpp) target_link_libraries(base PUBLIC Microsoft.GSL::GSL fmt::fmt Folly::folly) if(WIN32) target_link_libraries(base PUBLIC Ws2_32) diff --git a/works/life/computer-network-experiment/Common.cpp b/works/life/computer-network-experiment/Common.cpp index e4615fc..ec6fd1a 100644 --- a/works/life/computer-network-experiment/Common.cpp +++ b/works/life/computer-network-experiment/Common.cpp @@ -1,6 +1,6 @@ #include "Common.h" -#include "Output.h" +#include "IO.h" #ifdef WIN32 #include @@ -70,12 +70,6 @@ void BeforeExit() { SignalAndWaitForOutputThreadStop(); } -String ReadInputLine() { - String line; - std::getline(input_stream, line); - return line; -} - void SafeSend(int socket, std::string_view buffer) { const int total_byte_count = buffer.size(); int byte_count_sent = 0; diff --git a/works/life/computer-network-experiment/Common.h b/works/life/computer-network-experiment/Common.h index 6886e38..d2f2e52 100644 --- a/works/life/computer-network-experiment/Common.h +++ b/works/life/computer-network-experiment/Common.h @@ -2,6 +2,7 @@ #include "StringUtil.hpp" #include +#include #include #include @@ -9,6 +10,7 @@ using Char = wchar_t; using String = std::wstring; using StringView = std::wstring_view; +using StringStream = std::wstringstream; inline auto &input_stream = std::wcin; inline auto &output_stream = std::wcout; inline auto &error_stream = std::wcerr; @@ -25,6 +27,7 @@ inline std::string ConvertCharStringBack(StringView s) { using Char = char; using String = std::string; using StringView = std::string_view; +using StringStream = std::stringstream; inline auto &input_stream = std::cin; inline auto &output_stream = std::cout; inline auto &error_stream = std::cerr; @@ -43,7 +46,5 @@ int CloseSocket(int socket); void BeforeExit(); -String ReadInputLine(); - void SafeSend(int socket, std::string_view buffer); std::string SafeReadUntil(int socket, char c, std::string &rest); diff --git a/works/life/computer-network-experiment/IO.cpp b/works/life/computer-network-experiment/IO.cpp new file mode 100644 index 0000000..0c20537 --- /dev/null +++ b/works/life/computer-network-experiment/IO.cpp @@ -0,0 +1,80 @@ +#include "IO.h" + +#include + +#include +#include +#include +#include + +folly::MPMCQueue output_queue(100); + +folly::CancellationSource cancellation_source; + +std::thread io_thread; + +void PrintOutput(const Output &output) { + std::basic_ostream *stream; + + switch (output.type) { + case OutputType::Error: + stream = &error_stream; + break; + default: + stream = &output_stream; + break; + } + + switch (output.color) { + case OutputColor::Normal: + (*stream) << output.message; + break; + case OutputColor::Green: + (*stream) << CRUT("\x1b[32m") << output.message << CRUT("\x1b[39m") + << std::flush; + break; + case OutputColor::Red: + (*stream) << CRUT("\x1b[31m") << output.message << CRUT("\x1b[39m") + << std::flush; + break; + case OutputColor::Yellow: + (*stream) << CRUT("\x1b[33m") << output.message << CRUT("\x1b[39m") + << std::flush; + break; + } +} + +String ReadInputLine() { + String line; + std::getline(input_stream, line); + return line; +} + +void IOThread() { + while (true) { + if (cancellation_source.isCancellationRequested()) { + while (true) { + Output output; + if (output_queue.readIfNotEmpty(output)) { + PrintOutput(output); + } else { + return; + } + } + } + + Output output; + while (output_queue.readIfNotEmpty(output)) + PrintOutput(output); + + PrintOutput({CRUT("> ")}); + OnInputLine(ReadInputLine()); + } +} + +void SignalAndWaitForOutputThreadStop() { + cancellation_source.requestCancellation(); + io_thread.join(); +} + +void StartIOThread() { io_thread = std::thread(IOThread); } diff --git a/works/life/computer-network-experiment/IO.h b/works/life/computer-network-experiment/IO.h new file mode 100644 index 0000000..b0cf489 --- /dev/null +++ b/works/life/computer-network-experiment/IO.h @@ -0,0 +1,66 @@ +#pragma once +#include "Common.h" +#include "StringUtil.hpp" + +#include +#include +#include +#include + +#include +#include + +enum class OutputType { Normal, Error }; +enum class OutputColor { Normal, Green, Red, Yellow }; + +struct Output { + Output() = default; + Output(String message, OutputType type = OutputType::Normal) + : message(std::move(message)), type(type), + color(type == OutputType::Error ? OutputColor::Red + : OutputColor::Normal) {} + + Output(String message, OutputColor color) + : message(std::move(message)), type(OutputType::Normal), color(color) {} + + Output(String message, OutputType type, OutputColor color) + : message(std::move(message)), type(type), color(color) {} + + CRU_DEFAULT_COPY(Output) + CRU_DEFAULT_MOVE(Output) + ~Output() = default; + + String message; + OutputType type; + OutputColor color; +}; + +extern folly::MPMCQueue output_queue; + +inline void SendOutput(Output output) { + output_queue.blockingWrite(std::move(output)); +} + +inline void SendOutput(String output) { SendOutput(Output{std::move(output)}); } + +template void SendOutput(StringView format, Args &&...args) { + output_queue.blockingWrite(fmt::format(format, std::forward(args)...)); +} + +template +void SendOutput(OutputType type, StringView format, Args &&...args) { + output_queue.blockingWrite( + Output{fmt::format(format, std::forward(args)...), type}); +} + +template +void SendOutput(OutputColor color, StringView format, Args &&...args) { + output_queue.blockingWrite( + Output{fmt::format(format, std::forward(args)...), color}); +} + +void SignalAndWaitForOutputThreadStop(); + +void OnInputLine(StringView line); + +void StartIOThread(); diff --git a/works/life/computer-network-experiment/Output.cpp b/works/life/computer-network-experiment/Output.cpp deleted file mode 100644 index fbbd6ba..0000000 --- a/works/life/computer-network-experiment/Output.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "Output.h" - -#include - -#include -#include -#include - -std::mutex m; - -folly::MPMCQueue output_queue(100); - -folly::CancellationSource cancellation_source; - -std::thread output_thread(OutputThread); - -void PrintOutput(const Output &output) { - std::basic_ostream *stream; - - switch (output.type) { - case OutputType::Error: - stream = &error_stream; - break; - default: - stream = &output_stream; - break; - } - - switch (output.color) { - case OutputColor::Normal: - (*stream) << output.message; - break; - case OutputColor::Green: - (*stream) << CRUT("\x1b[32m") << output.message << CRUT("\x1b[39m") - << std::flush; - break; - case OutputColor::Red: - (*stream) << CRUT("\x1b[31m") << output.message << CRUT("\x1b[39m") - << std::flush; - break; - case OutputColor::Yellow: - (*stream) << CRUT("\x1b[33m") << output.message << CRUT("\x1b[39m") - << std::flush; - break; - } -} - -void OutputThread() { - while (true) { - std::lock_guard guard(m); - - if (cancellation_source.getToken().isCancellationRequested()) { - while (true) { - Output output; - if (output_queue.readIfNotEmpty(output)) { - PrintOutput(output); - } else { - return; - } - } - } - - Output output; - if (output_queue.readIfNotEmpty(output)) - PrintOutput(output); - } -} - -void SignalAndWaitForOutputThreadStop() { - cancellation_source.requestCancellation(); - output_thread.join(); -} - -std::lock_guard BlockOutputThread() { - return std::lock_guard(m); -} diff --git a/works/life/computer-network-experiment/Output.h b/works/life/computer-network-experiment/Output.h deleted file mode 100644 index 689c3d3..0000000 --- a/works/life/computer-network-experiment/Output.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include "Common.h" -#include "StringUtil.hpp" - -#include -#include -#include -#include - -#include -#include -#include - -enum class OutputType { Normal, Error }; -enum class OutputColor { Normal, Green, Red, Yellow }; - -struct Output { - Output() = default; - Output(String message, OutputType type = OutputType::Normal) - : message(std::move(message)), type(type), - color(type == OutputType::Error ? OutputColor::Red - : OutputColor::Normal) {} - - Output(String message, OutputColor color) - : message(std::move(message)), type(OutputType::Normal), color(color) {} - - Output(String message, OutputType type, OutputColor color) - : message(std::move(message)), type(type), color(color) {} - - CRU_DEFAULT_COPY(Output) - CRU_DEFAULT_MOVE(Output) - ~Output() = default; - - String message; - OutputType type; - OutputColor color; -}; - -extern folly::MPMCQueue output_queue; - -inline void SendOutput(Output output) { - output_queue.blockingWrite(std::move(output)); -} - -inline void SendOutput(String output) { SendOutput(Output{std::move(output)}); } - -template void SendOutput(StringView format, Args &&...args) { - output_queue.blockingWrite(fmt::format(format, std::forward(args)...)); -} - -template -void SendOutput(OutputType type, StringView format, Args &&...args) { - output_queue.blockingWrite( - Output{fmt::format(format, std::forward(args)...), type}); -} - -template -void SendOutput(OutputColor color, StringView format, Args &&...args) { - output_queue.blockingWrite( - Output{fmt::format(format, std::forward(args)...), color}); -} - -void OutputThread(); - -void SignalAndWaitForOutputThreadStop(); - -std::lock_guard BlockOutputThread(); diff --git a/works/life/computer-network-experiment/client.cpp b/works/life/computer-network-experiment/client.cpp index c25a26b..a8ce8cf 100644 --- a/works/life/computer-network-experiment/client.cpp +++ b/works/life/computer-network-experiment/client.cpp @@ -3,7 +3,7 @@ */ #include "Common.h" -#include "Output.h" +#include "IO.h" #ifdef WIN32 #include diff --git a/works/life/computer-network-experiment/server.cpp b/works/life/computer-network-experiment/server.cpp index 3c87ea0..7008c7b 100644 --- a/works/life/computer-network-experiment/server.cpp +++ b/works/life/computer-network-experiment/server.cpp @@ -3,8 +3,7 @@ */ #include "Common.h" -#include "Output.h" -#include "fmt/core.h" +#include "IO.h" #include #include @@ -25,7 +24,15 @@ const auto bind_address = "127.0.0.1"; // control bind address const u_short port = 1234; // control bind port +void PrintHelp() { + SendOutput(CRUT( + "Input and run one of following command:\n\t> NOTHING -> Continue and " + "print new messages.\n\t> list -> List all connected client.\n\t> send " + "[i] [message] -> Send messages to client with number i.\n")); +} + struct Connection { + int id; std::thread thread; int socket; sockaddr_in address; @@ -35,6 +42,8 @@ struct Connection { folly::CancellationSource cancellation_source; }; +std::vector connections; + void ResponseThreadProc(Connection *connection) { auto host = ConvertCharString(inet_ntoa(connection->address.sin_addr)); auto port = htons(connection->address.sin_port); @@ -77,9 +86,11 @@ void ResponseThreadProc(Connection *connection) { CloseSocket(connection->socket); } -int Main() { - std::vector connections; +void OnInputLine(StringView line) { StringStream ss{String(line)}; + ss. + } +int Main() { int server_socket; if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { @@ -105,6 +116,10 @@ int Main() { SendOutput(OutputColor::Green, CRUT("Now start to accept incoming connection.\n")); + StartIOThread(); + + int current_id = 1; + while (true) { sockaddr_in client_address; int client_socket; @@ -121,6 +136,7 @@ int Main() { } Connection connection; + connection.id = current_id++; connection.socket = client_socket; connection.address = client_address; connections.push_back(std::move(connection)); -- cgit v1.2.3