#include #include #include // ┐ #include // ├ inne pliku nagłówkowe dla winsock #pragma comment(lib, "Ws2_32.lib") // ┘ // pomocnicza funkcja dla prostszej obsługi błędów inline char *getLastErrorMessage() { static thread_local char msgBuf[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, WSAGetLastError(), 0, msgBuf, 1024, nullptr); return msgBuf; } int main(int c, char **a) { WSADATA wsadata{}; // ┐ no i standardowo trzeba WSAStartup(MAKEWORD(2, 2),&wsadata); // ┘ zainicjalizować winsock const char *port = (c < 2 ? "4444" : a[1]); int family = (c < 3 ? AF_INET6 : AF_INET), status; // zwróć uwagę że tutaj jest ustawiane też socktype addrinfo *res, hints{.ai_flags = AI_PASSIVE, .ai_family = family, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP}; if ((status = getaddrinfo(nullptr, port, &hints, &res))) { std::cerr << "Getaddrinfo failed: " << gai_strerror(status) << std::endl; return 1; } SOCKET s = socket(res->ai_family, res->ai_socktype, 0), one = 1, zero = 0; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)); // windows domyślnie dla AF_INET6 słucha tylko na IPv6; poniższa linia zmienia to zachowanie setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&zero, sizeof(zero)); if (bind(s, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) { std::cerr << "Bind failed: " << getLastErrorMessage() << std::endl; return 1; } freeaddrinfo(res); listen(s, 1); std::cout << "Listening on port " << port << std::endl; while (1) { sockaddr *cliAddr = (sockaddr *)new sockaddr_storage; socklen_t cliAddrLen = sizeof(sockaddr_storage); SOCKET c = accept(s, cliAddr, &cliAddrLen); if (c == INVALID_SOCKET) { perror("Bind failed"); return 1; } std::stringstream msg; msg << "Client connected from:" << std::endl; char host[NI_MAXHOST], port[NI_MAXSERV]; status = getnameinfo(cliAddr, cliAddrLen, host, NI_MAXHOST, port, NI_MAXSERV, 0); if (status) std::cerr << "Getnameinfo failed: " << gai_strerror(status) << std::endl; msg << "\r [resolved] address: " << host << " port: " << port << std::endl; status = getnameinfo(cliAddr, cliAddrLen, host, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); if (status) std::cerr << "Getnameinfo failed: " << gai_strerror(status) << std::endl; msg << " [numeric ] address: " << host << " port: " << port << std::endl; delete cliAddr; std::cout << msg.str() << std::flush; send(c, msg.str().c_str(), msg.str().length(), 0); shutdown(c, SD_BOTH); closesocket(c); } }