#include #include #include #include #include #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 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; }