diff options
author | crupest <crupest@outlook.com> | 2021-06-07 20:20:10 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-06-07 20:20:10 +0800 |
commit | c10e08c3896343cc7ddffe1dd7b1d09da2f8548e (patch) | |
tree | 9a62f500d177a4190a4c3b642a58a38e109e56ea /works/life | |
parent | 04bc88aca6157dfd1d2309b353d9feb64bcc8800 (diff) | |
download | crupest-c10e08c3896343cc7ddffe1dd7b1d09da2f8548e.tar.gz crupest-c10e08c3896343cc7ddffe1dd7b1d09da2f8548e.tar.bz2 crupest-c10e08c3896343cc7ddffe1dd7b1d09da2f8548e.zip |
import(life): ...
Diffstat (limited to 'works/life')
-rw-r--r-- | works/life/computer-network-experiment/Common.cpp | 70 | ||||
-rw-r--r-- | works/life/computer-network-experiment/Common.h | 5 | ||||
-rw-r--r-- | works/life/computer-network-experiment/Output.cpp | 11 | ||||
-rw-r--r-- | works/life/computer-network-experiment/Output.h | 3 | ||||
-rw-r--r-- | works/life/computer-network-experiment/client.cpp | 19 | ||||
-rw-r--r-- | works/life/computer-network-experiment/server.cpp | 29 |
6 files changed, 100 insertions, 37 deletions
diff --git a/works/life/computer-network-experiment/Common.cpp b/works/life/computer-network-experiment/Common.cpp index 5be3971..22f8b63 100644 --- a/works/life/computer-network-experiment/Common.cpp +++ b/works/life/computer-network-experiment/Common.cpp @@ -12,6 +12,8 @@ #include <sys/unistd.h>
#endif
+#include <string>
+
[[noreturn]] void PrintErrorMessageAndExit(StringView message,
bool print_last_error) {
@@ -40,6 +42,7 @@ }
#ifdef WIN32
+namespace {
void InitWSA() {
WSADATA wsa_data;
@@ -47,6 +50,8 @@ void InitWSA() { PrintErrorMessageAndExit(CRUT("Failed to initialize wsa."));
}
}
+} // namespace
+
#endif
int CloseSocket(int socket) {
@@ -65,6 +70,71 @@ 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;
+ int retry_count = 0;
+
+ while (true) {
+ // Now we have sent all data.
+ if (byte_count_sent == total_byte_count)
+ break;
+
+ 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;
+ }
+
+ byte_count_sent += byte_actually_sent;
+ }
+}
+
+std::string SafeReadUntil(int socket, char c, std::string &rest) {
+ std::string result = rest;
+
+ const int buffer_size = 100;
+ char *buffer = new char[buffer_size];
+
+ while (true) {
+ int received_number = recv(socket, buffer, buffer_size, 0);
+
+ if (received_number == -1) {
+ PrintErrorMessageAndExit(CRUT("Failed to recv."));
+ }
+
+ bool b = false;
+
+ for (int i = 0; i < received_number; i++) {
+ if (buffer[i] == '\n') {
+ result.append(buffer, i);
+ rest = std::string(buffer + i + 1, received_number - i - 1);
+ b = true;
+ break;
+ }
+ }
+
+ if (b)
+ break;
+
+ result.append(buffer, received_number);
+ }
+
+ delete[] buffer;
+
+ return result;
+}
+
int main() {
#ifdef WIN32
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
diff --git a/works/life/computer-network-experiment/Common.h b/works/life/computer-network-experiment/Common.h index e5612fd..c3b6094 100644 --- a/works/life/computer-network-experiment/Common.h +++ b/works/life/computer-network-experiment/Common.h @@ -41,3 +41,8 @@ void InitWSA(); 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/Output.cpp b/works/life/computer-network-experiment/Output.cpp index 2989c98..db97e5e 100644 --- a/works/life/computer-network-experiment/Output.cpp +++ b/works/life/computer-network-experiment/Output.cpp @@ -2,9 +2,12 @@ #include <folly/CancellationToken.h>
+#include <mutex>
#include <ostream>
#include <type_traits>
+std::mutex m;
+
folly::MPMCQueue<Output> output_queue(100);
folly::CancellationSource cancellation_source;
@@ -44,6 +47,8 @@ void PrintOutput(const Output &output) { void OutputThread() {
while (true) {
+ m.lock();
+
if (cancellation_source.getToken().isCancellationRequested()) {
while (true) {
Output output;
@@ -58,6 +63,8 @@ void OutputThread() { Output output;
if (output_queue.readIfNotEmpty(output))
PrintOutput(output);
+
+ m.unlock();
}
}
@@ -65,3 +72,7 @@ void SignalAndWaitForOutputThreadStop() { cancellation_source.requestCancellation();
output_thread.join();
}
+
+std::lock_guard<std::mutex> BlockOutputThread() {
+ return std::lock_guard<std::mutex>(m);
+}
diff --git a/works/life/computer-network-experiment/Output.h b/works/life/computer-network-experiment/Output.h index 2d16eb0..689c3d3 100644 --- a/works/life/computer-network-experiment/Output.h +++ b/works/life/computer-network-experiment/Output.h @@ -8,6 +8,7 @@ #include <folly/MPMCQueue.h>
#include <iostream>
+#include <mutex>
#include <thread>
enum class OutputType { Normal, Error };
@@ -63,4 +64,4 @@ void OutputThread(); void SignalAndWaitForOutputThreadStop();
-extern std::thread output_thread;
+std::lock_guard<std::mutex> BlockOutputThread();
diff --git a/works/life/computer-network-experiment/client.cpp b/works/life/computer-network-experiment/client.cpp index 922ecdc..2494bae 100644 --- a/works/life/computer-network-experiment/client.cpp +++ b/works/life/computer-network-experiment/client.cpp @@ -37,19 +37,16 @@ int Main() { PrintErrorMessageAndExit(CRUT("Failed to connect!"));
}
- const int buffer_size = 100;
- char *buffer = new char[buffer_size];
-
- int received_number = recv(client_socket, buffer, buffer_size, 0);
-
- if (received_number == -1) {
- PrintErrorMessageAndExit(CRUT("Failed to recv."));
+ String name;
+ {
+ auto guard = BlockOutputThread();
+ output_stream << CRUT("Please input your name:");
+ name = ReadInputLine();
}
- std::string s(buffer, received_number);
-
- SendOutput(OutputColor::Green, CRUT("Received message:\n"));
- SendOutput(OutputColor::Normal, CRUT("{}\n"), ConvertCharString(s));
+ String name_data = ConvertCharString(name);
+ SafeSend(client_socket,
+ std::string_view{name_data.data(), name_data.size() + 1});
CloseSocket(client_socket);
return 0;
diff --git a/works/life/computer-network-experiment/server.cpp b/works/life/computer-network-experiment/server.cpp index ac80125..2877c61 100644 --- a/works/life/computer-network-experiment/server.cpp +++ b/works/life/computer-network-experiment/server.cpp @@ -22,34 +22,13 @@ const u_short port = 1234; // control bind port void ResponseThreadProc(int socket, sockaddr_in address) {
auto address_string = inet_ntoa(address.sin_addr);
- SendOutput(CRUT("Connected to {}!\n"), ConvertCharString(address_string));
- const std::string_view buffer = "Love you!!! By crupest!";
+ std::string rest;
- const int total_byte_count = buffer.size();
- int byte_count_sent = 0;
- int retry_count = 0;
+ std::string name = SafeReadUntil(socket, '\n', rest);
- while (true) {
- // Now we have sent all data.
- if (byte_count_sent == total_byte_count)
- break;
-
- 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;
- }
-
- byte_count_sent += byte_actually_sent;
- }
-
- SendOutput(OutputColor::Green, CRUT("Succeeded to send message to {}!\n"),
- ConvertCharString(address_string));
+ SendOutput(CRUT("Connected to {}, whose name is {}."),
+ ConvertCharString(address_string), ConvertCharString(name));
CloseSocket(socket);
}
|