👉🏻 주요 변경사항은 아래와 같습니다.
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 %