๐๐ป ์ฃผ์ ๋ณ๊ฒฝ์ฌํญ์ ์๋์ ๊ฐ์ต๋๋ค.
The major changes are as follows.
โ๏ธ โ๏ธ ํ์๋ ๋ถ๋ถ์ด ๋ณ๊ฒฝ์ฌํญ์
๋๋ค.
The parts marked with โ๏ธ are the changes.
โ๏ธ 5080์http ์๋ฒ์ด๊ณ 6443์ https์๋ฒ์
๋๋ค. 6080์๋ฒ๋ ์ญ์ ํ์ต๋๋ค.
5080 is an HTTP server and 6443 is an HTTPS server. Server 6080 has been deleted.
โ๏ธ์๋ฒ ์ข
๋ฃ์์๋ handle_clientํจ์๊ฐ ์คํ๋์ด “[SSL] SSL_new() failed”๋ฉ์ธ์ง ์ถ๋ ฅ๋๋ ๋ฌธ์ ๋ฅผ ๊ต์ ํ์ต๋๋ค.
Fixed an issue where the handle_client function was executed and the “[SSL] SSL_new() failed” message was displayed even when the server was terminated.
— ์๋ฒ ์ข
๋ฃ ์์ ์ ssl_ctx๊ฐ ํด์ ๋์ด ๊ธฐ์กด์ ์์
์ค์ด๊ฑฐ๋ ์ฌ์คํ๋๋ ์ค๋ ๋์์ ์ค๋ฅ๋ฅผ ๋ฐ์์ํค๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
There was an issue where ssl_ctx was released at the time of server shutdown, causing errors in existing working or restarted threads.
— ๋ชจ๋ ์ค๋ ๋๋ฅผ ํด์ ํ ํ ssl_ctx๋ฅผ ํด์ ๋ฅผ ์คํํจ์ผ๋ก์จ ์ค๋ฅ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
I resolved the error by releasing ssl_ctx after releasing all threads.
โ๏ธ ์ค๋ฅ ๋ฉ์ธ์ง๋ SSL (https)์ฌ์ฉํ๋ HttpsServer.cpp์์ ๋ฐ์ํ์ง๋ง http๋ ๋์ผํ๊ฒ ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํ์ต๋๋ค.
The error message occurred in HttpsServer.cpp using SSL (https), but the structure was changed in the same way for http.
โ๏ธ exit ๋ช
๋ น์ด๋ก ์๋ฒ ์ข
๋ฃ์ ์ค๋ ๋๊ฐ ์์ ํ ์ ๋ฆฌ๋๊ธฐ๊น์ง ์ฝ๊ฐ์ ์๊ฐ์ด ์์๋ ์ ์์ต๋๋ค.
When terminating the server with the exit command, it may take some time for threads to be completely cleaned up.
๐๐ป์ฝ๋ / Code
โ๏ธ ์ค๋ ๋ ๋ฐฑํฐ์ ์ธ / Thread vector declaration
— HttpServer.h์ ์ค๋ ๋๋ฅผ ์ฎ๊ฒจ ๋ด์ ๋ฐฑํฐ๋ฅผ ์ ์ธํฉ๋๋ค.
Declare a vector to store threads in HttpServer.h.
std::vector<std::thread> client_threads;
โ๏ธ ๋ฃจํํ์ถ,์ค๋ ๋ ์ ์ฅ / Loop escape, thread save
— HttpsServer.cpp,Server.cpp
— running.load() ๊ฐ false์ด๋ฉด while๋ฃจํ ํ์ถํ๊ณ ์ค๋ ๋๋ฅผ ๋ฐฑํฐ์ ์ ์ฅํฉ๋๋ค.
If running.load() is false, exit the while loop and save the thread to the vector.
while (running.load()) {
// ๋ฃจํํ์ถ / Loop escape โ๏ธ
if (!running.load()) {
break; // ์ข
๋ฃ ์ ํธ ๋ฐ์ผ๋ฉด ๋ฃจํ ์ข
๋ฃ / Terminate the loop when the termination signal is received.
}
... ์ค๋ต / skipping the middle...
if (running.load() && client_socket < 0) {
// ๋ฃจํํ์ถ / Loop escape โ๏ธ
if (!running.load()) {
break; // ์์ผ ๋ซํ์ ์คํจํ ๊ฒฝ์ฐ ์ข
๋ฃ / Terminate if failed due to socket closing
}
perror("accept failed");
continue;
}
// ํด๋ผ์ด์ธํธ ์ ์ / Client connected
std::thread client_thread([this, client_socket]() {
//์ธ๋ถ์์ ๋ฉ์ธ์ง ๋ฐ๊พธ๊ธฐ / Change message externally
this->handle_client(client_socket);
});
// ์ค๋ ๋ - ๋ฐฑํฐ์ ์ ์ฅ / Thread - Stored in a vectorโ๏ธ
client_threads.push_back(std::move(client_thread));
//client_thread.detach(); // ์ด์ ์ฝ๋ / previous codeโ๏ธ
}
โ๏ธ ์ค๋ ๋ ์ข
๋ฃ ํ ssl_ctx์คํ
Execute ssl_ctx after thread termination
— for๋ฌธ์ผ๋ก ๋ฐฑํฐ์ ์ ์ฅ๋ ์ค๋ ๋๋ฅผ ํ๋์ฉ ์ฌ์ฉ์ค์ธ์ง ํ์ธ(joinable()ํ๊ณ ์ฌ์ฉ์ค์ด ์๋๋ฉด(joinable() == true) ์ค๋ ๋๊ฐ ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐ(join())ํฉ๋๋ค.
Use a for loop to check each thread stored in the vector one by one if it is in use (joinable()), and if it is not in use (joinable() == true), wait until the thread terminates (join()).
— ๋ชจ๋ ์ค๋ ๋๊ฐ ๋๊ธฐ์ํ๊ฐ๋๋ฉด ์ค๋ ๋๋ฅผ ์ข
๋ฃ ํฉ๋๋ค.(client_threads.clear();)
Terminates threads when all threads are in a waiting state.(client_threads.clear();)
— ์ค๋ ๋ ์ข
๋ฃ๊ฐ ์๋ฃ๋๋ฉด ssl_ctx๋ฅผ ํด์ ํฉ๋๋ค.
Release ssl_ctx when thread termination is complete.
— HttpsServer.cpp stop() ํจ์ / function
void https::Server::stop() {
try {
if (running.load() && server_fd != -1) {
... ์ค๋ต / skipping the middle ...
// ๋ชจ๋ ํด๋ผ์ด์ธํธ ์ค๋ ๋ ์ข
๋ฃ ๋๊ธฐโ๏ธโ๏ธ
for (auto& t : client_threads) {
if (t.joinable()) {
t.join();
}
}
client_threads.clear();
// SSL ์ปจํ
์คํธ ํด์ (์กด์ฌํ๋ค๋ฉด) / Release SSL context (if any)
if (ssl_ctx) {
SSL_CTX_free(ssl_ctx);
ssl_ctx = nullptr;
}
// OpenSSL ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋ฆฌ / OpenSSL Library Cleanup โ๏ธโ๏ธ
// OpenSSL 3.x์์๋ ๋ณ๋์ ์ ๋ฆฌ ํจ์ ํธ์ถ ๋ถํ์ํฉ๋๋ค.
//EVP_cleanup();
std::cout << "[Server] Shutdown initiated." << std::endl;
}
} catch (const std::exception& e) {
std::cerr << "[ERROR] Exception during shutdown: " << e.what() << std::endl;
} catch (...) {
std::cerr << "[ERROR] Unknown exception during shutdown." << std::endl;
}
}
๐๐ป ๋น๋ / Build
cd build
cmake ..
make
๐๐ป ์คํ / Run
./main
๐๐ป ํฐ๋ฏธ๋ ์คํ ๊ฒฐ๊ณผ / Terminal execution result
MacBookAir build % ./main
[SSL] SSL context successfully initialized
--- Starting Server Application ---
Server listening on port 5080...
Https Server listening on port 6443...
CMD> exit
[INFO] ์ข
๋ฃ ๋ช
๋ น์ ๋ฐ์์ต๋๋ค. ์๋น์ค ์ข
๋ฃ๋ฅผ ์์ํฉ๋๋ค.
[INFO] Received a shutdown command. Starting service shutdown.
[Server] Shutdown initiated.
[Server] Shutdown initiated.
[MAIN] Server Application Finished.
MacBookAir build %