{"id":5433,"date":"2026-04-22T20:54:51","date_gmt":"2026-04-22T11:54:51","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=5433"},"modified":"2026-04-22T20:54:51","modified_gmt":"2026-04-22T11:54:51","slug":"webserver-miniwebserver-2","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/04\/22\/webserver-miniwebserver-2\/","title":{"rendered":"[Webserver]miniWebserver \u2013 (2)"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \uc774\uc804 \ucf54\ub4dc\uc5d0\uc11c \uac00\ub3c5\uc131\uc744 \uc704\ud574\uc11c \ud30c\uc77c\uc744 \ubd84\ub9ac\ud588\uc2b5\ub2c8\ub2e4.<br>I separated the files in the previous code for readability.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb Main.cpp\uc5d0\uc11c \uc11c\ubc84 \uc2dc\uc791\ubd80\ubd84\uc744 \uc4f0\ub808\ub4dc\ub85c \ubd84\ub9ac\ud588\uc2b5\ub2c8\ub2e4.<br>I separated the server startup part into a thread in Main.cpp.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \u2757\ufe0f\ub85c \ud45c\uc2dc\ub41c \ubd80\ubd84\uc740 \uae30\uc874\ucf54\ub4dc\uc5d0\uc11c \ubc14\ub010 \ub0b4\uc6a9\uc785\ub2c8\ub2e4.<br>The parts marked with \u2757\ufe0f are the changes made to the existing code.<\/p>\n\n\n\n<p>\u2714\ufe0f Server.h<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;string&gt;\n\nclass Server {\npublic:\n    \/\/ \uc0dd\uc131\uc790: \uc11c\ubc84 \ucd08\uae30\ud654 (IP, Port)\n    \/\/ Constructor: Initialize server (IP, Port)\n    Server(const std::string&amp; ip, int port);\n\n    \/\/ \uc11c\ubc84 \uc18c\ucf13 \ud30c\uc77c \ub514\uc2a4\ud06c\ub9bd\ud130\ub97c \uc800\uc7a5\ud560 \uba64\ubc84 \ubcc0\uc218\n    \/\/ Member variable to store server socket file descriptors\n    int server_fd = -1; \/\/ \u2757\ufe0f\n\n    \/\/ \uc11c\ubc84 \uc2e4\ud589 \ud568\uc218: \ub9ac\uc2a4\ub2dd\uc744 \uc2dc\uc791\ud558\uace0 \uba54\uc778 \ub8e8\ud504\ub97c \ub3cc\ub9bc\n    \/\/ Server execution function: Starts listening and runs the main loop\n    bool start();\n\n    \/\/ \uc11c\ubc84 \uc885\ub8cc (\ud544\uc694\ud558\ub2e4\uba74)\n    \/\/ Shut down the server (if necessary)\n    void stop();\n\nprivate:\n    std::string ip_address;\n    int port_number;\n\n    \/\/ \uc2e4\uc81c \ub9ac\uc2a4\ub2dd \ubc0f \uc5f0\uacb0 \uc218\uc2e0 \ub85c\uc9c1 (\ub0b4\ubd80 \uad6c\ud604)\n    \/\/ Actual listening and connection reception logic (internal implementation)\n    void run_listener();\n\n    \/\/ \uc5f0\uacb0 \ucc98\ub9ac \ub85c\uc9c1 (\uc2a4\ub808\ub4dc \ud480 \ub610\ub294 \ubcc4\ub3c4 \ud578\ub4e4\ub7ec\uc5d0\uac8c \uc704\uc784)\n    \/\/ Connection handling logic (delegated to thread pool or separate handler)\n    void handle_client(int client_socket);\n};\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Server.cpp<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"Server.h\"\n#include &lt;iostream&gt;\n#include &lt;cstring&gt;\n#include &lt;unistd.h&gt;\n#include &lt;sys\/socket.h&gt;\n#include &lt;netinet\/in.h&gt;\n#include &lt;thread&gt;\n#include &lt;vector&gt;\n\n\/\/#define PORT 5080 \u2757\ufe0f\n#define BACKLOG 10 \/\/ \ub300\uae30 \ud050 \ud06c\uae30 \/ wait queue size\n\nServer::Server(const std::string&amp; ip, int port)\n    : ip_address(ip), port_number(port) {}\n\nvoid Server::run_listener() {\n    \/\/std::cout &lt;&lt; \"&#91;INFO] Server listening on \" &lt;&lt; ip_address &lt;&lt; \":\" &lt;&lt; port_number &lt;&lt; std::endl;\n\n    \/\/ --- 1. \uc18c\ucf13 \uc0dd\uc131 (Socket Creation) --- \/\/\n    \/\/int server_fd = socket(AF_INET, SOCK_STREAM, 0);\n    \/\/ \uba64\ubc84 \ubcc0\uc218\ub85c \ubcc0\uacbd \/ Change to member variable\u2757\ufe0f\n    server_fd = socket(AF_INET, SOCK_STREAM, 0);\n\n    \/\/if (server_fd == 0) { \u2757\ufe0f\n    if (server_fd == -1) {\n        perror(\"socket failed\");\n        exit(EXIT_FAILURE);\n    }\n\n    int opt = 1;\n    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &amp;opt, sizeof(opt)) &lt; 0) {\n        perror(\"setsockopt\");\n        exit(EXIT_FAILURE);\n    }\n\n    \/\/ --- 2. \ubc14\uc778\ub529 (Binding) --- \/\/\n    struct sockaddr_in address;\n    address.sin_family = AF_INET;         \/\/ IPv4\n    address.sin_addr.s_addr = INADDR_ANY; \/\/ \ubaa8\ub4e0 \uc778\ud130\ud398\uc774\uc2a4 IP \uc0ac\uc6a9 \/ Use all interface IPs\n    address.sin_port = htons(port_number);       \/\/ \ud3ec\ud2b8\ub97c \ub124\ud2b8\uc6cc\ud06c \ubc14\uc774\ud2b8 \uc21c\uc11c\ub85c \ubcc0\ud658 \/ Convert ports to network byte order\n\n    if (bind(server_fd, (struct sockaddr *)&amp;address, sizeof(address)) &lt; 0) {\n        perror(\"bind failed\");\n        close(server_fd);\n        exit(EXIT_FAILURE);\n    }\n\n    \/\/ --- 3. \ub9ac\uc2a4\ub2dd \uc2dc\uc791 (setsockopt: listen_socket(socket)) --- \/\/\n    if (listen(server_fd, BACKLOG) &lt; 0) {\n        perror(\"listen failed\");\n        close(server_fd);\n        exit(EXIT_FAILURE);\n    }\n    std::cout &lt;&lt; \"Server listening on port \" &lt;&lt; port_number &lt;&lt; \"...\" &lt;&lt; std::endl;\n\n    \/\/ --- 4. \uba54\uc778 \ub8e8\ud504 (Accept loop): \ud074\ub77c\uc774\uc5b8\ud2b8 \uc5f0\uacb0\uc744 \ubb34\ud55c\ud788 \uae30\ub2e4\ub9bc \/ Infinitely waiting for client connections --- \/\/\n    while (true) {\n\n        \/\/ IPv4\uad6c\uc870\uccb4 \/ Structure for IPv4 address\n        struct sockaddr_in client_address;\n\n        \/\/ \uc8fc\uc18c \uad6c\uc870\uccb4\uac00 \uba54\ubaa8\ub9ac\uc5d0\uc11c \ucc28\uc9c0\ud558\ub294 \ubc14\uc774\ud2b8 \ud06c\uae30\ub97c \uc800\uc7a5\ud558\ub294 \ubcc0\uc218\uc758 \ud0c0\uc785\n        \/\/ Type of the variable storing the byte size occupied by the address structure in memory\n        socklen_t addrlen = sizeof(client_address);\n\n        \/\/ accept() \ud568\uc218\uac00 \ube14\ub85c\ud0b9(Blocking) \uc0c1\ud0dc\uc5d0\uc11c \ud074\ub77c\uc774\uc5b8\ud2b8 \uc5f0\uacb0\uc744 \uae30\ub2e4\ub9bc\n        \/\/ The accept() function waits for client connections in a blocking state.\n        int client_socket = accept(server_fd, (struct sockaddr *)&amp;client_address, &amp;addrlen);\n        if (client_socket &lt; 0) {\n            perror(\"accept failed\");\n            continue; \/\/ \uc2e4\ud328\ud588\uc73c\uba74 \ub2e4\uc74c \ub8e8\ud504\ub97c \ub3cc\uba70 \uc7ac\uc2dc\ub3c4 \/ Retry in the next loop if it fails\n        }\n\n        \/\/ \ub3d9\uc2dc\uc131 \ucc98\ub9ac: \uc0c8\ub85c\uc6b4 \uc5f0\uacb0\uc774 \uc624\uba74 \uc0c8\ub85c\uc6b4 \uc4f0\ub808\ub4dc\ub97c \uc0dd\uc131\ud558\uc5ec \ucc98\ub9ac\n        \/\/ Concurrency Handling: When a new connection arrives, create a new thread to handle it.\n        \/\/std::thread client_thread(Server::handle_client, client_socket);\n        \/\/\n        \/\/ \ub78c\ub2e4 {&#91;](){...}} \ub294 \ud604\uc7ac \uc2a4\ub808\ub4dc\uac00 Server \uac1d\uccb4(this)\uc758 \ub9e5\ub77d\uc744 \uc720\uc9c0\ud558\uba70 \uc2e4\ud589\ub418\ub3c4\ub85d \ubcf4\uc7a5\ud569\ub2c8\ub2e4.\n        \/\/ Lambda {&#91;](){...}} ensures that the current thread executes while maintaining the context of the Server object (this).\n        std::thread client_thread(&#91;this, client_socket]() {\n            this-&gt;handle_client(client_socket);\n        });\n        \/\/ \uc4f0\ub808\ub4dc\ub97c \ubd84\ub9ac\ud558\uace0 \uba54\uc778 \ub8e8\ud504\ub97c \uacc4\uc18d \uc2e4\ud589\ud558\uac8c \ud568\n        \/\/ Detach the thread so that the main loop continues running.\n        client_thread.detach();\n    }\n}\n\/\/\u2757\ufe0f\nvoid Server::handle_client(int client_socket) {\n    char buffer&#91;1024];\n    std::cout &lt;&lt; \"&#91;Connection] New client connected.\" &lt;&lt; std::endl;\n\n    \/\/ 1. \ub370\uc774\ud130 \uc218\uc2e0 \/ receive data (Read)\n    ssize_t bytes_read = read(client_socket, buffer, sizeof(buffer) - 1);\n    if (bytes_read &gt; 0) {\n        buffer&#91;bytes_read] = '\\0'; \/\/ C-string\n        std::string request = buffer;\n        std::cout &lt;&lt; \"&#91;Received] \" &lt;&lt; request.substr(0, 30) &lt;&lt; \"...\" &lt;&lt; std::endl;\n\n        \/\/ 2. \uc751\ub2f5 \uc804\uc1a1 \/ send response(Write)\n        const char* response = \"HTTP\/1.1 200 OK\\r\\nContent-Type: text\/html; charset=utf-8\\r\\n\\r\\n&lt;h1&gt;\ud83d\udc4bHi~ Hi~ Hi~~~!&lt;\/h1&gt;&lt;p&gt;Welcome to the miniWebserver!&lt;\/p&gt;\";\n        write(client_socket, response, strlen(response));\n    }\n\n    \/\/ 3. \uc5f0\uacb0 \uc885\ub8cc \/ close connection\n    close(client_socket);\n    std::cout &lt;&lt; \"&#91;Connection] Client disconnected.\" &lt;&lt; std::endl;\n}\n\nbool Server::start() {\n    \/\/ \uc11c\ubc84\uac00 \uc2e4\uc81c\ub85c \uc791\ub3d9\ud558\ub294 \uba54\uc778 \ud568\uc218 \/ Main function that actually runs the server\n    try {\n        run_listener();\n    } catch (const std::exception&amp; e) {\n        std::cerr &lt;&lt; \"&#91;ERROR] Server failed to start: \" &lt;&lt; e.what() &lt;&lt; std::endl;\n        return false;\n    }\n    return true;\n}\n\nvoid Server::stop() {\n    \/\/ \uc11c\ubc84\ub97c \uc885\ub8cc\ud558\ub294 \ud568\uc218 \/ Function to stop the server\n    \/\/close(server_fd);\u2757\ufe0f\n    if (server_fd != -1) {\n        \/\/ \uba64\ubc84 \ubcc0\uc218\uc5d0 \uc800\uc7a5\ub41c \uac12\uc744 \uc0ac\uc6a9\ud558\uc5ec \uc885\ub8cc\ud569\ub2c8\ub2e4. \/ Use the value stored in the member variable to stop the server\n        close(server_fd);\n        server_fd = -1; \/\/ \ub2eb\uc558\uc73c\ubbc0\ub85c \ucd08\uae30\ud654 \/ Initialize to -1 after closing\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Main.cpp<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"Server.h\"\n#include &lt;iostream&gt;\n#include &lt;thread&gt;\n#include &lt;chrono&gt;\n#include &lt;atomic&gt;\n#include &lt;string&gt;\n\nint main() {\n\n    \/\/ 1. \uc11c\ubc84 \uc778\uc2a4\ud134\uc2a4 \uc0dd\uc131 \/ Create server instance\n    Server my_server(\"127.0.0.1\", 5080); \n    std::thread server_thread(&amp;Server::start, &amp;my_server); \/\/ \uc11c\ubc84 \uc2dc\uc791 \/ Start server \u2757\ufe0f\n    std::cout &lt;&lt; \"--- Starting Server Application ---\" &lt;&lt; std::endl;\n\n    \/\/ 2. \uc885\ub8cc \ub85c\uc9c1 (\uc11c\ubc84\uac00 \uc885\ub8cc\ub418\uc9c0 \uc54a\uae30 \ub584\ubb38\uc5d0 \uc2e4\ud589\ub418\uc9c0 \uc54a\uc74c,\ub098\uc911\uc744 \uc704\ud55c \uc885\ub8cc \ub85c\uc9c1)\n    \/\/ Termination logic (not executed because the server has not terminated, termination logic for later)\n    server_thread.join();\n    my_server.stop();\n\n    return 0;\n}\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f \ucef4\ud30c\uc77c \/ Compiling<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>g++ Server.cpp Main.cpp -o server -std=c++17 -pthread<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f\uc2e4\ud589 \/ Run<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/server<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb \uc774\uc804 \ucf54\ub4dc\uc5d0\uc11c \uac00\ub3c5\uc131\uc744 \uc704\ud574\uc11c \ud30c\uc77c\uc744 \ubd84\ub9ac\ud588\uc2b5\ub2c8\ub2e4.I separated the files in the previous code for readability. \ud83d\udc49\ud83c\udffb Main.cpp\uc5d0\uc11c \uc11c\ubc84 \uc2dc\uc791\ubd80\ubd84\uc744 \uc4f0\ub808\ub4dc\ub85c \ubd84\ub9ac\ud588\uc2b5\ub2c8\ub2e4.I separated the server startup part into a thread in Main.cpp. \ud83d\udc49\ud83c\udffb \u2757\ufe0f\ub85c \ud45c\uc2dc\ub41c \ubd80\ubd84\uc740 \uae30\uc874\ucf54\ub4dc\uc5d0\uc11c \ubc14\ub010 \ub0b4\uc6a9\uc785\ub2c8\ub2e4.The parts marked with \u2757\ufe0f are the changes made to the existing code. \u2714\ufe0f Server.h \u2714\ufe0f Server.cpp [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23,1],"tags":[],"class_list":["post-5433","post","type-post","status-publish","format-standard","hentry","category-cpp","category-uncategorized","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/5433","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=5433"}],"version-history":[{"count":1,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/5433\/revisions"}],"predecessor-version":[{"id":5434,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/5433\/revisions\/5434"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=5433"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=5433"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=5433"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}