C++/네트워크

다시써보는 에코서버2 window 버전

교쟁이 2024. 6. 2. 08:46

이전버전에서 쓰레드를 추가했다.

 

#include <iostream>
#include <winsock2.h>
#include <WS2tcpip.h>
#include <array>
#include <thread>
#include <vector>

#pragma comment(lib, "ws2_32.lib")


auto EchoHandler(SOCKET clientSocket)->void{
    int receiveSize;
    std::array<char, 128> receivedBuffer;

    while ((receiveSize = ::recv(clientSocket, receivedBuffer.data(), receivedBuffer.size(), 0)) > 0) {
        ::send(clientSocket, receivedBuffer.data(), receiveSize, 0);
        std::cout.write(receivedBuffer.data(), receiveSize);
        std::cout << std::endl;
        receivedBuffer.fill(0);
    }
    if (receiveSize == SOCKET_ERROR) {
        std::cerr << "Receive failed." << std::endl;
    }
    ::closesocket(clientSocket);
    std::cout << "클라이언트가 연결이 끊겼습니다." << std::endl;
}


int main() {
    WSADATA wsaData;
    if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cerr << "WSAStartup failed." << std::endl;
        return 1;
    }

    SOCKET listenSocket = ::socket(AF_INET, SOCK_STREAM, 0);
    if (listenSocket == INVALID_SOCKET) {
        std::cerr << "Failed to create socket." << std::endl;
        ::WSACleanup();
        return 1;
    }

    constexpr uint16_t port = 8888;
    SOCKADDR_IN serverAddress{
        .sin_family = AF_INET,
        .sin_port = htons(port),
        .sin_addr{.S_un{.S_addr = htonl(INADDR_ANY)}},
        //.sin_addr{.S_un{.S_addr = inet_addr("192.168.35.154")}},
    };

    if (::bind(listenSocket, reinterpret_cast<SOCKADDR*>(&serverAddress), sizeof(serverAddress)) == SOCKET_ERROR) {
        std::cerr << "Bind failed." << std::endl;
        ::closesocket(listenSocket);
        ::WSACleanup();
        return 1;
    }

    if (::listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) {
        std::cerr << "Listen failed." << std::endl;
        ::closesocket(listenSocket);
        ::WSACleanup();
        return 1;
    }

    SOCKET clientSocket;
    SOCKADDR_IN clientAddress;
    int clientAddressSize = sizeof(clientAddress);


    std::vector<std::thread> echoHandlers;
    while ((clientSocket = ::accept(listenSocket, 
        reinterpret_cast<SOCKADDR*>(&clientAddress), 
        &clientAddressSize)) != INVALID_SOCKET) {
        std::cout << "새 클라이언트가 연결되었습니다." << std::endl;
        echoHandlers.emplace_back(EchoHandler, clientSocket);
    }

    for (auto &handler : echoHandlers) {
        if(handler.joinable())
            handler.join();
    }

    ::closesocket(listenSocket);
    ::WSACleanup();
    return 0;
}