add necessary CMake files

This commit is contained in:
12hydrogen
2026-04-03 20:51:58 +08:00
parent bf14011d64
commit d0b566773e
10 changed files with 351 additions and 190 deletions
+2
View File
@@ -46,3 +46,5 @@
# Built Visual Studio Code Extensions # Built Visual Studio Code Extensions
*.vsix *.vsix
build
compile_commands.json
+31
View File
@@ -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"
},
]
}
+5
View File
@@ -0,0 +1,5 @@
{
"cSpell.words": [
"WSADATA"
]
}
+28
View File
@@ -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"
}
]
}
+33
View File
@@ -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
)
+31
View File
@@ -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;
}
View File
+24
View File
@@ -0,0 +1,24 @@
#include <thread>
#include <mutex>
#include <future>
#include <atomic>
#include <condition_variable>
#include <memory>
#include <vector>
#include <forward_list>
template <typename T>
struct Message {
std::unique_ptr<T> payload;
};
template <typename T>
struct Queue {
std::forward_list<Message<T>> queue;
};
template <typename T>
struct Tunnel {};
+114 -190
View File
@@ -1,206 +1,130 @@
#include <stdio.h> #include "socket.hpp"
#include <WinSock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <memory>
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
struct WSA { WSA::WSA(WORD version) {
WSADATA wsa; int result = WSAStartup(version, &wsa);
if (result) throw result;
}
WSA::~WSA() noexcept {
WSACleanup();
}
explicit WSA(WORD version = MAKEWORD(2, 2)) { AddrInfoPtr::AddrInfoPtr() noexcept:
int result = WSAStartup(version, &wsa); info(nullptr) {}
if (result) throw result; AddrInfoPtr::~AddrInfoPtr() noexcept {
} freeaddrinfo(info);
~WSA() noexcept { }
WSACleanup();
}
};
struct AddrInfoPtr {
struct addrinfo *info;
AddrInfoPtr() noexcept: addrinfo** AddrInfoPtr::operator&() noexcept {
info(nullptr) {} return &info;
}
addrinfo& AddrInfoPtr::operator*() noexcept {
return *info;
}
addrinfo* AddrInfoPtr::operator->() noexcept {
return info;
}
~AddrInfoPtr() noexcept { const addrinfo& AddrInfoPtr::operator*() const noexcept {
freeaddrinfo(info); return *info;
} }
auto operator->() noexcept { AddrInfoPtr::operator addrinfo *() noexcept {
return info; return info;
} }
auto operator&() noexcept { AddrInfo::AddrInfo() noexcept {
return &info; ZeroMemory(&info, sizeof(info));
} }
auto& operator*() noexcept { addrinfo* AddrInfo::operator->() noexcept {
return *info; return &info;
} }
addrinfo* AddrInfo::operator&() noexcept {
return &info;
}
const auto& operator*() const noexcept { AddrInfo::operator const addrinfo&() const noexcept {
return *info; return info;
} }
AddrInfo::operator addrinfo&() noexcept {
operator addrinfo*() noexcept { return info;
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<char[]> 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;
AddrInfoPtr AddrInfo::get_addrinfo(PCSTR node, PCSTR service) {
AddrInfoPtr ptr; AddrInfoPtr ptr;
AddrInfo hints; int result = getaddrinfo(node, service, &info, &ptr);
if (result == SOCKET_ERROR) throw result;
hints->ai_family = AF_INET; return ptr;
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;
} }
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;
} }
+83
View File
@@ -0,0 +1,83 @@
#include <stdio.h>
#include <WinSock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <memory>
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<char[]> data;
int size;
Buffer(int len);
char* get();
const char* get() const;
int len() const;
};