diff options
author | crupest <crupest@outlook.com> | 2021-05-27 15:13:46 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-05-27 15:13:46 +0800 |
commit | a1192a14c6a52e8ab77e1c84e38b65aa5e250bec (patch) | |
tree | 50d2653f664a6aaf5593da6837b78294dc9715f5 /works/life | |
parent | 6c0e4b64fa9967b2a2ef7dfb840cab3a8325f67e (diff) | |
download | crupest-a1192a14c6a52e8ab77e1c84e38b65aa5e250bec.tar.gz crupest-a1192a14c6a52e8ab77e1c84e38b65aa5e250bec.tar.bz2 crupest-a1192a14c6a52e8ab77e1c84e38b65aa5e250bec.zip |
import(life): Add computer network experiment.
Diffstat (limited to 'works/life')
-rw-r--r-- | works/life/computer-network-experiment/.clangd | 2 | ||||
-rw-r--r-- | works/life/computer-network-experiment/.gitignore | 2 | ||||
-rw-r--r-- | works/life/computer-network-experiment/client.cpp | 66 | ||||
-rw-r--r-- | works/life/computer-network-experiment/server.cpp | 132 | ||||
-rw-r--r-- | works/life/main.cpp | 36 |
5 files changed, 238 insertions, 0 deletions
diff --git a/works/life/computer-network-experiment/.clangd b/works/life/computer-network-experiment/.clangd new file mode 100644 index 0000000..c28ae22 --- /dev/null +++ b/works/life/computer-network-experiment/.clangd @@ -0,0 +1,2 @@ +CompileFlags:
+ Add: [-std=c++17]
diff --git a/works/life/computer-network-experiment/.gitignore b/works/life/computer-network-experiment/.gitignore new file mode 100644 index 0000000..43561d4 --- /dev/null +++ b/works/life/computer-network-experiment/.gitignore @@ -0,0 +1,2 @@ +*.exe
+*.pdb
diff --git a/works/life/computer-network-experiment/client.cpp b/works/life/computer-network-experiment/client.cpp new file mode 100644 index 0000000..926ece6 --- /dev/null +++ b/works/life/computer-network-experiment/client.cpp @@ -0,0 +1,66 @@ +/** Created by crupest.
+ * This is the client program.
+ */
+
+#include <Windows.h>
+#include <iostream>
+#include <string>
+#include <winsock.h>
+
+#pragma comment(lib, "ws2_32.lib")
+
+const auto connect_address = "127.0.0.1"; // control connect address
+const u_short port = 1234; // control connect port
+
+int main() {
+ WSADATA wsa_data;
+
+ if (WSAStartup(MAKEWORD(2, 2), &wsa_data)) // initialize wsa
+ {
+ std::cerr << "WSA start up error!\n";
+ WSACleanup();
+ return 1;
+ }
+
+ int client_socket;
+
+ if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
+ std::cerr << "Failed to create socket!\n";
+ WSACleanup();
+ return 1;
+ }
+
+ sockaddr_in server_address;
+
+ server_address.sin_family = AF_INET;
+ server_address.sin_port = htons(port);
+ server_address.sin_addr.s_addr = inet_addr(connect_address);
+ memset(&(server_address.sin_zero), 0, sizeof(server_address.sin_zero));
+
+ if (connect(client_socket, (sockaddr *)&server_address, sizeof(sockaddr)) ==
+ SOCKET_ERROR) {
+ std::cerr << "Failed to connect!";
+ WSACleanup();
+ return 1;
+ }
+
+ 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) {
+ std::cerr << "Failed to recv.";
+ WSACleanup();
+ return 1;
+ }
+
+ std::string s(buffer, received_number);
+
+ std::cout << "Received message:\n" << s;
+
+ closesocket(client_socket);
+ WSACleanup();
+
+ return 0;
+}
diff --git a/works/life/computer-network-experiment/server.cpp b/works/life/computer-network-experiment/server.cpp new file mode 100644 index 0000000..1b196a9 --- /dev/null +++ b/works/life/computer-network-experiment/server.cpp @@ -0,0 +1,132 @@ +/** Created by crupest.
+ * This is the server program.
+ */
+
+#include <cstdlib>
+#include <ios>
+#include <iostream>
+#include <mutex>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <thread>
+
+#include <Windows.h>
+#include <winsock.h>
+
+#pragma comment(lib, "Ws2_32.lib")
+
+const auto bind_address = "127.0.0.1"; // control bind address
+const u_short port = 1234; // control bind port
+
+// As far as I know, cout is not thread safe. So we need a lock. But this might
+// not be the best solution. We can use a queue instead to avoid block.
+std::mutex cout_mutex;
+
+[[noreturn]] void
+PrintErrorMessageAndExit(std::wstring_view message,
+ std::optional<int> error_code = std::nullopt) {
+ std::wcerr << message << L'\n';
+
+ if (error_code) {
+ std::cerr << L"Error code is " << std::hex << *error_code << L'\n';
+ wchar_t buffer[500];
+ if (!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ nullptr, *error_code, 0, buffer, 500, nullptr)) {
+ std::wcerr << L"Failed to format error message.\n";
+ } else {
+ std::wcerr << buffer << L'\n';
+ }
+ }
+
+ WSACleanup();
+
+ std::exit(1);
+}
+
+void ResponseThreadProc(int socket, sockaddr_in address) {
+ auto address_string = inet_ntoa(address.sin_addr);
+ {
+ std::lock_guard<std::mutex> guard(cout_mutex);
+ std::cout << "Connected to " << address_string << "!\n";
+ }
+
+ const std::string_view buffer = "Love you!!! By crupest!";
+
+ 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 == SOCKET_ERROR) {
+ std::lock_guard<std::mutex> guard(cout_mutex);
+ std::cerr << "Failed to send!\n";
+ closesocket(socket);
+ break;
+ }
+
+ byte_count_sent += byte_actually_sent;
+ }
+
+ {
+ std::lock_guard<std::mutex> guard(cout_mutex);
+ std::cout << "Succeeded to send message to " << address_string << "!\n";
+ }
+}
+
+int main() {
+ WSADATA wsa_data;
+
+ if (WSAStartup(MAKEWORD(2, 2), &wsa_data)) { // initialize wsa
+ PrintErrorMessageAndExit(L"Failed to initialize wsa.", WSAGetLastError());
+ }
+
+ int server_socket;
+
+ if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
+ PrintErrorMessageAndExit(L"Failed to create socket.", WSAGetLastError());
+ }
+
+ sockaddr_in server_address;
+
+ server_address.sin_family = AF_INET;
+ server_address.sin_port = htons(port);
+ server_address.sin_addr.s_addr = inet_addr(bind_address);
+ memset(&(server_address.sin_zero), 0, sizeof(server_address.sin_zero));
+
+ if (bind(server_socket, reinterpret_cast<sockaddr *>(&server_address),
+ sizeof(sockaddr_in)) == SOCKET_ERROR) {
+ PrintErrorMessageAndExit(L"Failed to bind.", WSAGetLastError());
+ }
+
+ if (listen(server_socket, SOMAXCONN) == SOCKET_ERROR) {
+ PrintErrorMessageAndExit(L"Failed to listen.", WSAGetLastError());
+ }
+
+ while (true) {
+ sockaddr_in client_address;
+ int client_socket;
+ int sin_size = sizeof(sockaddr_in);
+ client_socket =
+ accept(server_socket, reinterpret_cast<sockaddr *>(&client_address),
+ &sin_size);
+
+ if (client_socket == INVALID_SOCKET) {
+ PrintErrorMessageAndExit(L"Failed to accecpt", WSAGetLastError());
+ }
+
+ std::thread response_thread(ResponseThreadProc, client_socket,
+ client_address);
+ response_thread.detach();
+ }
+}
diff --git a/works/life/main.cpp b/works/life/main.cpp new file mode 100644 index 0000000..efb5bff --- /dev/null +++ b/works/life/main.cpp @@ -0,0 +1,36 @@ +#include <WinSock2.h>
+#include <Windows.h>
+#include <cassert>
+#include <iostream>
+#include <iphlpapi.h>
+#include <string>
+
+std::wstring ToString(const SOCKET_ADDRESS &addr) {
+ DWORD buffer_length = 100;
+ wchar_t buffer[100];
+ auto error = WSAAddressToStringW(addr.lpSockaddr, addr.iSockaddrLength, NULL,
+ buffer, &buffer_length);
+ assert(error == 0);
+ return std::wstring(buffer);
+}
+
+int main() {
+ WSADATA wsaData;
+ int error = WSAStartup(MAKEWORD(2, 0), &wsaData);
+ assert(error == 0);
+
+ ULONG buffer_size = 100000;
+ PIP_ADAPTER_ADDRESSES_LH buffer =
+ (PIP_ADAPTER_ADDRESSES_LH)malloc(buffer_size);
+ ULONG error2 = GetAdaptersAddresses(
+ AF_INET,
+ GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS |
+ GAA_FLAG_INCLUDE_ALL_INTERFACES | GAA_FLAG_SKIP_MULTICAST,
+ NULL, buffer, &buffer_size);
+ assert(error2 == ERROR_SUCCESS);
+
+ std::wcout << ToString(buffer->FirstPrefix->Address) << L"\n";
+ std::wcout << buffer->FirstGatewayAddress << L"\n";
+
+ return 0;
+}
|