diff --git a/.gitignore b/.gitignore index 46fefa8..47f4767 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ # Built Visual Studio Code Extensions *.vsix +build +compile_commands.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..600b5ad --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(Windows) 启动", + "type": "cppvsdbg", + "request": "launch", + "program": "${fileDirname}\\${fileBasenameNoExtension}.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "console": "integratedTerminal", + "preLaunchTask": "C/C++: cl.exe 生成活动文件" + }, + { + "name": "(Windows) 启动 CMake 目标", + "type": "cppvsdbg", + "request": "launch", + "program": "${command:cmake.launchTargetPath}", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "console": "integratedTerminal" + }, + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..86e062d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "WSADATA" + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..bc67677 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: cl.exe 生成活动文件", + "command": "cl.exe", + "args": [ + "/Zi", + "/EHsc", + "/nologo", + "/Fe${fileDirname}\\${fileBasenameNoExtension}.exe", + "${file}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$msCompile" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "编译器: cl.exe" + } + ] +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fd49c6d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.10) + +project(WinSock2Wrapper) + +set(C_STANDARD 17) +set(CXX_STANDARD 17) +set(C_STANDARD_REQUIRED True) +set(CXX_STANDARD_REQUIRED True) + +add_library( + wrapper + ./socket.cpp +) + +target_include_directories( + wrapper + PUBLIC . +) + +add_executable( + test_server + ./main.cpp +) + +target_include_directories( + test_server + PUBLIC . +) + +target_link_libraries( + test_server + PUBLIC wrapper +) diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..1023f26 --- /dev/null +++ b/main.cpp @@ -0,0 +1,31 @@ +#include "socket.hpp" + +int main(int argc, char **argv) try { + int iResult = 0; + + WSA wsa; + + AddrInfoPtr ptr; + AddrInfo hints; + + hints->ai_family = AF_INET; + hints->ai_socktype = SOCK_STREAM; + hints->ai_protocol = IPPROTO_TCP; + hints->ai_flags = AI_PASSIVE; + + AddrInfoPtr result = hints.get_addrinfo(NULL, "8088"); + + Socket listen_socket; + + listen_socket.from_addrinfo(*ptr, Socket::BIND); + + Socket client_socket = listen_socket.accept_client(); + + return 0; +} +catch (const int &err) { + return err; +} +catch (...) { + return -1; +} diff --git a/pool.cpp b/pool.cpp new file mode 100644 index 0000000..e69de29 diff --git a/pool.hpp b/pool.hpp new file mode 100644 index 0000000..7047d79 --- /dev/null +++ b/pool.hpp @@ -0,0 +1,24 @@ +#include + +#include +#include +#include +#include + +#include + +#include +#include + +template +struct Message { + std::unique_ptr payload; +}; + +template +struct Queue { + std::forward_list> queue; +}; + +template +struct Tunnel {}; diff --git a/socket.cpp b/socket.cpp index 850c20f..826b5a7 100644 --- a/socket.cpp +++ b/socket.cpp @@ -1,206 +1,130 @@ -#include - -#include -#include -#include - -#include +#include "socket.hpp" #pragma comment(lib, "ws2_32.lib") -struct WSA { - WSADATA wsa; +WSA::WSA(WORD version) { + int result = WSAStartup(version, &wsa); + if (result) throw result; +} +WSA::~WSA() noexcept { + WSACleanup(); +} - explicit WSA(WORD version = MAKEWORD(2, 2)) { - int result = WSAStartup(version, &wsa); - if (result) throw result; - } - ~WSA() noexcept { - WSACleanup(); - } -}; +AddrInfoPtr::AddrInfoPtr() noexcept: +info(nullptr) {} +AddrInfoPtr::~AddrInfoPtr() noexcept { + freeaddrinfo(info); +} -struct AddrInfoPtr { - struct addrinfo *info; - AddrInfoPtr() noexcept: - info(nullptr) {} +addrinfo** AddrInfoPtr::operator&() noexcept { + return &info; +} +addrinfo& AddrInfoPtr::operator*() noexcept { + return *info; +} +addrinfo* AddrInfoPtr::operator->() noexcept { + return info; +} - ~AddrInfoPtr() noexcept { - freeaddrinfo(info); - } +const addrinfo& AddrInfoPtr::operator*() const noexcept { + return *info; +} - auto operator->() noexcept { - return info; - } +AddrInfoPtr::operator addrinfo *() noexcept { + return info; +} - auto operator&() noexcept { - return &info; - } +AddrInfo::AddrInfo() noexcept { + ZeroMemory(&info, sizeof(info)); +} - auto& operator*() noexcept { - return *info; - } +addrinfo* AddrInfo::operator->() noexcept { + return &info; +} +addrinfo* AddrInfo::operator&() noexcept { + return &info; +} - const auto& operator*() const noexcept { - return *info; - } - - operator addrinfo*() noexcept { - return info; - } -}; - -struct AddrInfo { - struct addrinfo info; - - AddrInfo() noexcept { - ZeroMemory(&info, sizeof(info)); - } - ~AddrInfo() noexcept = default; - - auto operator->() noexcept { - return &info; - } - - auto operator&() noexcept { - return &info; - } - - operator const addrinfo&() const noexcept { - return info; - } - - operator addrinfo&() noexcept { - return info; - } - - auto get_addrinfo(PCSTR node, PCSTR service) { - AddrInfoPtr ptr; - int result = getaddrinfo(node, service, &info, &ptr); - if (result == SOCKET_ERROR) throw result; - return ptr; - } -}; - -struct Socket { - enum AddrAction { - NO_ACTION, - CONNECT, - BIND, - }; - - SOCKET s; - - explicit Socket(SOCKET init = INVALID_SOCKET) noexcept: - s(init) {} - - ~Socket() noexcept { - closesocket(s); - } - - operator SOCKET() const noexcept { - return s; - } - - bool is_valid() const noexcept { - return s != INVALID_SOCKET; - } - - explicit operator bool() const noexcept { - return is_valid(); - } - - void from_addrinfo(const struct addrinfo &info, AddrAction action = NO_ACTION) { - s = socket(info.ai_family, info.ai_socktype, info.ai_protocol); - if (s == INVALID_SOCKET) throw -1; - - switch (action) { - case NO_ACTION: - break; - case CONNECT: - int result = connect(s, info.ai_addr, (int)info.ai_addrlen); - if (result == SOCKET_ERROR) throw result; - break; - case BIND: - int result = bind(s, info.ai_addr, (int)info.ai_addrlen); - if (result == SOCKET_ERROR) throw result; - result = listen(s, SOMAXCONN); - if (result == SOCKET_ERROR) throw result; - break; - } - } - - Socket accept_client() const noexcept { - return Socket(accept(s, NULL, NULL)); - } -}; - -struct Connection { - Socket s; - struct sockaddr addr; - - explicit Connection(Socket listen) noexcept { - int len = 0; - s = Socket(accept(listen, &addr, &len)); - } - - void stop_send() const { - int result = shutdown(s, SD_SEND); - if (result == SOCKET_ERROR) throw result; - } - - int send_data(const Buffer &data) const { - return send(s, data.get(), data.len(), 0); - } -}; - -struct Buffer { - std::unique_ptr data; - int size; - - Buffer(int len): - size(len), data(new char[len]) {} - - const char* get() const { - return data.get(); - } - - char* get() { - return data.get(); - } - - int len() const { - return size; - } -}; - -int main(int argc, char **argv) try { - int iResult = 0; - - WSA wsa; +AddrInfo::operator const addrinfo&() const noexcept { + return info; +} +AddrInfo::operator addrinfo&() noexcept { + return info; +} +AddrInfoPtr AddrInfo::get_addrinfo(PCSTR node, PCSTR service) { AddrInfoPtr ptr; - AddrInfo hints; - - hints->ai_family = AF_INET; - hints->ai_socktype = SOCK_STREAM; - hints->ai_protocol = IPPROTO_TCP; - hints->ai_flags = AI_PASSIVE; - - AddrInfoPtr result = hints.get_addrinfo(NULL, "8088"); - - Socket listen_socket; - - listen_socket.from_addrinfo(*ptr, Socket::BIND); - - Connection conn(listen_socket); - - return 0; + int result = getaddrinfo(node, service, &info, &ptr); + if (result == SOCKET_ERROR) throw result; + return ptr; } -catch (const int &err) { - return err; + +Socket::Socket(SOCKET init) noexcept: +s(init) {} +Socket::~Socket() noexcept { + closesocket(s); } -catch (...) { - return -1; + +Socket::operator SOCKET() const noexcept { + return s; +} + +Socket::operator bool() const noexcept { + return is_valid(); +} + +bool Socket::is_valid() const noexcept { + return s != INVALID_SOCKET; +} + +void Socket::from_addrinfo(const addrinfo &info, AddrAction action) { + s = socket(info.ai_family, info.ai_socktype, info.ai_protocol); + if (s == INVALID_SOCKET) throw -1; + int result = SOCKET_ERROR; + switch (action) { + case NO_ACTION: + break; + case CONNECT: + result = connect(s, info.ai_addr, (int)info.ai_addrlen); + if (result == SOCKET_ERROR) throw result; + break; + case BIND: + result = bind(s, info.ai_addr, (int)info.ai_addrlen); + if (result == SOCKET_ERROR) throw result; + result = listen(s, SOMAXCONN); + if (result == SOCKET_ERROR) throw result; + break; + } +} + +Socket Socket::accept_client() const noexcept { + return Socket(accept(s, NULL, NULL)); +} + +void Socket::stop_send() const { + int result = shutdown(s, SD_SEND); + if (result == SOCKET_ERROR) throw result; +} + +int Socket::send_data(const Buffer &data) const { + return send(s, data.get(), data.len(), 0); +} + +int Socket::recv_data(Buffer &data) const { + return recv(s, data.get(), data.len(), 0); +} + +Buffer::Buffer(int len): +size(len), data(new char[len]) {} + +char *Buffer::get() { + return data.get(); +} +const char *Buffer::get() const { + return data.get(); +} + +int Buffer::len() const { + return size; } diff --git a/socket.hpp b/socket.hpp new file mode 100644 index 0000000..1104cac --- /dev/null +++ b/socket.hpp @@ -0,0 +1,83 @@ +#include + +#include +#include +#include + +#include + +struct WSA { + WSADATA wsa; + + explicit WSA(WORD version = MAKEWORD(2, 2)); + ~WSA() noexcept; +}; + +struct AddrInfoPtr { + struct addrinfo *info; + + AddrInfoPtr() noexcept; + ~AddrInfoPtr() noexcept; + + addrinfo** operator&() noexcept; + addrinfo& operator*() noexcept; + addrinfo* operator->() noexcept; + const addrinfo& operator*() const noexcept; + + operator addrinfo*() noexcept; +}; + +struct AddrInfo { + struct addrinfo info; + + AddrInfo() noexcept; + ~AddrInfo() noexcept = default; + + addrinfo* operator->() noexcept; + addrinfo* operator&() noexcept; + + operator const addrinfo&() const noexcept; + operator addrinfo&() noexcept; + + AddrInfoPtr get_addrinfo(PCSTR node, PCSTR service); +}; + +struct Socket { + enum AddrAction { + NO_ACTION, + CONNECT, + BIND, + }; + + SOCKET s; + struct sockaddr addr; + + explicit Socket(SOCKET init = INVALID_SOCKET) noexcept; + ~Socket() noexcept; + + operator SOCKET() const noexcept; + + explicit operator bool() const noexcept; + bool is_valid() const noexcept; + + void from_addrinfo(const struct addrinfo &info, AddrAction action = NO_ACTION); + + Socket accept_client() const noexcept; + + void stop_send() const; + + int send_data(const Buffer &data) const; + int recv_data(Buffer &data) const; +}; + +struct Buffer { + std::unique_ptr data; + int size; + + Buffer(int len); + + char* get(); + const char* get() const; + + int len() const; +};