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/computer-network-experiment | |
| parent | 04bc88aca6157dfd1d2309b353d9feb64bcc8800 (diff) | |
| download | crupest-c10e08c3896343cc7ddffe1dd7b1d09da2f8548e.tar.gz crupest-c10e08c3896343cc7ddffe1dd7b1d09da2f8548e.tar.bz2 crupest-c10e08c3896343cc7ddffe1dd7b1d09da2f8548e.zip  | |
import(life): ...
Diffstat (limited to 'works/life/computer-network-experiment')
| -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);
  }
  | 
