From f7d73f1bf08aaca98e789a6d6c56d672cc0c4c9f Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 8 Jun 2021 18:25:36 +0800 Subject: import(life): ... --- works/life/computer-network-experiment/Common.cpp | 33 ++++++++++------------ works/life/computer-network-experiment/Common.h | 6 ++-- works/life/computer-network-experiment/client.cpp | 11 ++++++-- works/life/computer-network-experiment/server.cpp | 34 ++++++++++++++++++----- 4 files changed, 53 insertions(+), 31 deletions(-) diff --git a/works/life/computer-network-experiment/Common.cpp b/works/life/computer-network-experiment/Common.cpp index ec6fd1a..1df4d56 100644 --- a/works/life/computer-network-experiment/Common.cpp +++ b/works/life/computer-network-experiment/Common.cpp @@ -1,6 +1,7 @@ #include "Common.h" #include "IO.h" +#include #ifdef WIN32 #include @@ -70,7 +71,7 @@ void BeforeExit() { SignalAndWaitForOutputThreadStop(); } -void SafeSend(int socket, std::string_view buffer) { +bool SafeSend(int socket, std::string_view buffer) { const int total_byte_count = buffer.size(); int byte_count_sent = 0; int retry_count = 0; @@ -78,55 +79,49 @@ void SafeSend(int socket, std::string_view buffer) { while (true) { // Now we have sent all data. if (byte_count_sent == total_byte_count) - break; + return true; auto byte_actually_sent = send(socket, buffer.data() + byte_count_sent, buffer.size() - byte_count_sent, 0); // send failed if (byte_actually_sent == -1) { - SendOutput(OutputType::Error, CRUT("Failed to send!\n")); - CloseSocket(socket); - break; + return false; } byte_count_sent += byte_actually_sent; } } -std::string SafeReadUntil(int socket, char c, std::string &rest) { - std::string result = rest; +bool SafeReadUntil(int socket, char c, std::string &data, std::string &rest) { + data = rest; const int buffer_size = 100; - char *buffer = new char[buffer_size]; + char buffer[buffer_size]; while (true) { int received_number = recv(socket, buffer, buffer_size, 0); if (received_number == -1) { - PrintErrorMessageAndExit(CRUT("Failed to recv.")); + return false; } - bool b = false; + bool end = false; for (int i = 0; i < received_number; i++) { if (buffer[i] == c) { - result.append(buffer, i); + data.append(buffer, i); rest = std::string(buffer + i + 1, received_number - i - 1); - b = true; + end = true; break; } } - if (b) - break; + if (end) + return true; - result.append(buffer, received_number); + data.append(buffer, received_number); } - - delete[] buffer; - - return result; } int main() { diff --git a/works/life/computer-network-experiment/Common.h b/works/life/computer-network-experiment/Common.h index a4472c7..1e6c277 100644 --- a/works/life/computer-network-experiment/Common.h +++ b/works/life/computer-network-experiment/Common.h @@ -48,5 +48,7 @@ int CloseSocket(int socket); void BeforeExit(); -void SafeSend(int socket, std::string_view buffer); -std::string SafeReadUntil(int socket, char c, std::string &rest); +// Return false for error. +bool SafeSend(int socket, std::string_view buffer); +// Return false for error. +bool SafeReadUntil(int socket, char c, std::string &data, std::string &rest); diff --git a/works/life/computer-network-experiment/client.cpp b/works/life/computer-network-experiment/client.cpp index c206856..73ae52f 100644 --- a/works/life/computer-network-experiment/client.cpp +++ b/works/life/computer-network-experiment/client.cpp @@ -75,9 +75,12 @@ int Main() { break; } - std::string s = SafeReadUntil(client_socket, '\n', rest); + std::string data; + if (!SafeReadUntil(client_socket, '\n', data, rest)) { + PrintErrorMessageAndExit(CRUT("Failed to receive message.\n")); + } - SendOutput(CRUT("Recived a message:\n{}\n"), ConvertCharString(s)); + SendOutput(CRUT("Recived a message:\n{}\n"), ConvertCharString(data)); } }); receive_thread.detach(); @@ -89,7 +92,9 @@ int Main() { std::string s; if (send_queue.read(s)) { - SafeSend(client_socket, s); + if (!SafeSend(client_socket, s)) { + PrintErrorMessageAndExit(CRUT("Failed to send message to server.")); + } } } diff --git a/works/life/computer-network-experiment/server.cpp b/works/life/computer-network-experiment/server.cpp index 9654687..03d27ad 100644 --- a/works/life/computer-network-experiment/server.cpp +++ b/works/life/computer-network-experiment/server.cpp @@ -36,6 +36,7 @@ void PrintHelp() { struct Connection { int id; std::thread thread; + std::thread receive_thread; int socket; sockaddr_in address; String address_string; @@ -65,13 +66,19 @@ void ResponseThreadProc(Connection *connection) { connection->address_string = fmt::format(CRUT("{}:{}"), host, port); std::string rest; + std::string name_data; + if (!SafeReadUntil(connection->socket, '\n', name_data, rest)) { + SendOutput(OutputType::Error, CRUT("Failed to read name of {}.\n"), + connection->address_string); + CloseSocket(connection->socket); + return; + } - std::string n = SafeReadUntil(connection->socket, '\n', rest); - connection->name = ConvertCharString(n); + connection->name = ConvertCharString(name_data); SendOutput(OutputColor::Green, CRUT("Connected to {}, whose name is {}.\n"), connection->address_string, connection->name); - std::thread revieve_thread( + connection->receive_thread = std::thread( [](Connection *connection) { std::string rest; while (true) { @@ -79,14 +86,22 @@ void ResponseThreadProc(Connection *connection) { break; } - std::string s = SafeReadUntil(connection->socket, '\n', rest); + std::string data; + + if (!SafeReadUntil(connection->socket, '\n', data, rest)) { + SendOutput(OutputType::Error, + CRUT("Failed read data from socket of {}({}).\n"), + connection->name, connection->address_string); + connection->cancellation_source.requestCancellation(); + return; + } SendOutput(CRUT("{}({}) send a message:\n{}\n"), connection->name, - connection->address_string, ConvertCharString(s)); + connection->address_string, ConvertCharString(data)); } }, connection); - revieve_thread.detach(); + connection->receive_thread.detach(); while (true) { if (connection->cancellation_source.isCancellationRequested()) { @@ -95,7 +110,12 @@ void ResponseThreadProc(Connection *connection) { std::string s; if (connection->send_queue.read(s)) { - SafeSend(connection->socket, s); + if (!SafeSend(connection->socket, s)) { + SendOutput(OutputType::Error, CRUT("Failed send data to {}({}).\n"), + connection->name, connection->address_string); + connection->cancellation_source.requestCancellation(); + break; + } } } -- cgit v1.2.3