일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- delete function
- c++ multi chatting room
- constructor
- return by reference
- C++
- virtual inheritance
- vector capacity
- std::ostream
- vector size
- this call
- dynamic_cast
- std::endl
- member function pointer
- conversion constructor
- pointer to member data
- std::cout
- virtual function
- increment operator
- diamond inheritance
- new&delete
- virtual destructor
- c++ basic practice
- suffix return type
- 더 지니어스 양면포커
- virtual function table
- operator overloading
- placement new
- discord bot
- base from member
- std::vector
- Today
- Total
I'm FanJae.
[C++ Server, C# Client] Day 4. Server 핸들러 로직 분할 본문
[C++ Server, C# Client] Day 4. Server 핸들러 로직 분할
FanJae 2024. 9. 29. 23:451. Handler Logic 분할 이유
- 서버가 처리하는게 많아지면 함수를 분리하는 것이 보기가 훨씬 깔끔해진다.
- 구현하는 입장에서도 특정 이벤트에 대한 처리를 어디서 하는지 확실히 알 수 있어 편해진다.
2. Client_Handle.h
const std::string CLOSE_SOCKET = "/Close_Socket";
const std::string COMPLETE_CREATE_ROOM = "/Complete_Create_Room";
const std::string EXIST_ROOM = "/Exist_Room";
const std::string NOT_EXIST_ROOM = "/Not_Exist_Room";
const std::string NO_ROOM = "/No_Room";
const std::string EXIT_ROOM = "/Exit_Room";
const std::string GET_CHATTING_ROOM = "/Get_Chatting_Room";
const std::string HANDLE_CREATE_CHATTING_ROOM = "/Create_Chatting_Room ";
const std::string HANDLE_JOIN_CHATTING_ROOM = "/Join_Chatting_Room ";
void ConnectClient(SOCKET clientSocket);
class ClientEventHandler
{
private:
SOCKET socket;
std::string roomName;
void Handle_Get_Chatting_Room();
void Handle_Exit_Room();
void Handle_Create_Chatting_Room(const std::string& message);
void Handle_Join_Chatting_Room(const std::string& message);
public:
ClientEventHandler(SOCKET clientSocket);
bool handleMessage(const std::string& message);
};
- ClientEventHandler 라는 객체를 만들었다.
- 이 객체는 클라이언트가 연결된 시점부터 연결이 끊기는 순간까지만 할당되고 공유자원도 아니다.
3. Client_Handle.cpp()
3-1. ConnectClient() 구현
void ConnectClient(SOCKET clientSocket)
{
ClientEventHandler handler(clientSocket);
char buffer[1024];
std::string str_buffer;
std::cout << "[Log] Client Connect! " << "clientSocket : " << clientSocket << std::endl;
while (true)
{
bool message_handle = false;
int recv_length = recv(clientSocket, buffer, sizeof(buffer), 0);
if (recv_length <= 0)
{
break;
}
buffer[recv_length] = '\0';
str_buffer = buffer;
std::cout << "[Log] " << str_buffer << std::endl;
message_handle = handler.handleMessage(str_buffer);
if (!message_handle) break;
}
closesocket(clientSocket);
}
- 서버가 연결을 시도하면 가장 먼저 이 작업이 반복적으로 수행된다.
- 서버는 연결된 소켓으로 부터 계속 메시지를 받아오고, 이 메시지를 받아서 handleMessage 함수에 넘겨준다.
- 그러면 이 함수에서 각 이벤트에 맞게 처리하도록 구현을 하였다.
- recv()는 받은 문자열의 길이를 반환하기 때문에 0이하이면 소켓을 닫도록 처리한다.
3-2. handleMessage() 구현
bool ClientEventHandler::handleMessage(const std::string& message)
{
if(message.substr(0,GET_CHATTING_ROOM.length()) == GET_CHATTING_ROOM)
{
Handle_Get_Chatting_Room();
}
else if (message.substr(0, EXIT_ROOM.length()) == EXIT_ROOM)
{
Handle_Exit_Room();
}
else if (message.substr(0, HANDLE_CREATE_CHATTING_ROOM.length()) == HANDLE_CREATE_CHATTING_ROOM)
{
Handle_Create_Chatting_Room(message.substr(HANDLE_CREATE_CHATTING_ROOM.length(), message.length()));
}
else if (message.substr(0, HANDLE_JOIN_CHATTING_ROOM.length()) == HANDLE_JOIN_CHATTING_ROOM)
{
Handle_Join_Chatting_Room(message.substr(HANDLE_JOIN_CHATTING_ROOM.length(), message.length()));
}
else if (message.substr(0, CLOSE_SOCKET.length()) == CLOSE_SOCKET)
{
std::cout << "[Log] : Client disconnected : " << message << std::endl;
return false;
}
else
{
std::cout << "[Log] : roomName : " << this->roomName << std::endl;
for (SOCKET target_socket : chatRooms[this->roomName])
{
send(target_socket, message.c_str(),message.length(), 0);
}
}
return true;
}
- 각 이벤트(Client_Handle.h)에 따라서, 적당히 이벤트를 처리하도록 만든다.
- 본인의 경우는 Client가 메시지를 보낼때, 방 이름을 보내는 경우에는 /Join_Room 방 이름과 같은 형태로 약속했다.
- 클라이언트 측에서 닫기 이벤트등으로 소켓을 닫는다면 서버에서도 Client와의 연결을 끊도록 만든다.
3-3. handleMessage() 구현 (메시지 처리)
void ClientEventHandler::Handle_Get_Chatting_Room()
{
std::string room_List = "";
if (chatRooms.empty())
{
room_List += NO_ROOM;
}
else
{
for (auto& room : chatRooms)
{
room_List += room.first + "\n";
}
}
send(socket, room_List.c_str(), room_List.length(), 0);
}
- 채팅룸이 존재하는 경우에는 채팅룸의 리스트를 보낸다.
- 하지만 채팅룸이 없는 경우에는 NO_ROOM("/No_Room")을 보내서 처리한다.
3-4. Handle_Exit_Room() 구현 (채팅방 나가기)
void ClientEventHandler::Handle_Exit_Room()
{
chatRooms[roomName].erase(this->socket);
if (chatRooms[roomName].empty())
{
chatRooms.erase(roomName);
}
}
- 사용자가 방을 나갔다는 것은 특정 방에 인원이 제거 된다는 것이다.
- 해당 인원을 방에서 제거하고, 방에 혹시 아무도 없다면 그 방은 삭제 해준다.
3-5. Handle_Create_Chatting_Room() 구현 (채팅방 생성)
void ClientEventHandler::Handle_Create_Chatting_Room(const std::string& message)
{
this->roomName = message;
std::string send_message = "";
if (chatRooms.find(roomName) != chatRooms.end())
{
send_message = EXIST_ROOM;
send(socket, send_message.c_str(), send_message.length(), 0);
}
else
{
std::cout << "[Log] : Client Create Room : " << message << std::endl;
chatRooms[message].insert(socket);
send_message = roomName;
send(socket, send_message.c_str(), send_message.length(), 0);
}
}
- 채팅 방이 있는지 확인하고 없으면 만들어준다. 있으면 EXIST_ROOM("/Exist_Room") 을 보내도록 처리했다.
3-6. Handle_Join_chatting_Room() 구현 (채팅방 입장)
void ClientEventHandler::Handle_Join_Chatting_Room(const std::string& message)
{
this->roomName = message;
std::string send_message = "";
if (chatRooms.find(roomName) != chatRooms.end())
{
send_message = roomName;
chatRooms[message].insert(socket);
send(socket, send_message.c_str(), send_message.length(), 0);
}
else
{
send_message = NOT_EXIST_ROOM;
send(socket, send_message.c_str(), send_message.length(), 0);
}
}
- 채팅 방이 존재하면, 해당 방에 입장 (Map에 insert로 처리하였다.)
- 없으면, NOT_EXIST_ROOM("/Not_Exist_Room")을 보내도록 처리한다.
- 위와 같이 처리한 이후에 이제 서버는 어떤 부분에 동기화가 필요할지 체크해야 한다.
TODO
1) Server
- 동기화 처리 필요
2) Client
- 각 상황에 맞는 버튼 이벤트 구현 필요
'Toy Project > Multi Room Cheating Server' 카테고리의 다른 글
[C++ Server, C# Client] Day 6. Client Event 구현 II, Server 동기화 처리 (0) | 2024.10.01 |
---|---|
[C++ Server, C# Client] Day 5. Server 오류 수정 및 Client Event 구현 I (0) | 2024.09.30 |
[C++ Server, C# Client] Day 3. GUI 클라이언트 설계 및 Server 버그 수정 (0) | 2024.09.26 |
[C++ Server] Day 2. Thread 적용 및 Multi Chatting Room 구현 (3) | 2024.09.25 |
[C++ Server] Day 1. Echo Server 구현. (0) | 2024.09.25 |