add necessary CMake files
This commit is contained in:
@@ -46,3 +46,5 @@
|
|||||||
# Built Visual Studio Code Extensions
|
# Built Visual Studio Code Extensions
|
||||||
*.vsix
|
*.vsix
|
||||||
|
|
||||||
|
build
|
||||||
|
compile_commands.json
|
||||||
|
|||||||
Vendored
+31
@@ -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"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"WSADATA"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+28
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
)
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
@@ -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
@@ -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;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user