Files
winsock2_wrapper/socket.cpp
T

207 lines
3.9 KiB
C++
Raw Normal View History

2026-03-27 19:56:56 +08:00
#include <stdio.h>
#include <WinSock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <memory>
#pragma comment(lib, "ws2_32.lib")
struct WSA {
WSADATA wsa;
explicit WSA(WORD version = MAKEWORD(2, 2)) {
int result = WSAStartup(version, &wsa);
if (result) throw result;
}
~WSA() noexcept {
WSACleanup();
}
};
struct AddrInfoPtr {
struct addrinfo *info;
AddrInfoPtr() noexcept:
info(nullptr) {}
~AddrInfoPtr() noexcept {
freeaddrinfo(info);
}
auto operator->() noexcept {
return info;
}
auto operator&() noexcept {
return &info;
}
auto& 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<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 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;
}
catch (const int &err) {
return err;
}
catch (...) {
return -1;
}