이전 게시글에서는 Iocp를 돌리기위한 다양한 클래스들을 만들고 accept와 recv까지 구현했다.
이번엔 send를 구현해서 특정 클라이언트로부터 받은 데이터를 접속한 다른 모든 클라이언트에게 뿌려주도록 해보자.
수정사항들
RecvBuffer, sendBuffer 클래스 추가
- authserver에서 그대로 가져옴 (변경 필요할 수 있음)
Session
- 기존 BYTE배열 버퍼를 sendBufferQueue로 변경
- 기존 BYTE배열 버퍼를 RecvBuffer로 변경
- 각종 recv, send, connect, disconnect 이벤트를 멤머변수로 가짐.
- weak_ptr<service> 멤버변수 추가.
- RegisterSend, ProcessSend, RegisterDisconnect, ProcessDisconnect 추가됨.
- recv한 데이터를 service의 broadcast 함수로 접속한 모든 유저에게 뿌려주도록 만듦. (테스트용)
Listener, Session
- register에서 ~event->init, setOwner 하고 process에서 Clear 해야만 함.
IocpCore
- RegisterHandle이 iocpObjectRef 를 받도록 수정함.
IocpEvent
- RecvEvent, SendEvent 추가함.
- SendEvent는 sendbuffers 벡터를 가짐. WSASend에 이 버퍼를 넣음.
- AcceptEvent 생성자 변경됨
- IocpEvent에 setter 추가함.
Service
- CreateSession 함수 추가. 세션 생성용.
- broad_cast_test 함수 추가
- set<SessionRef> _sessions 와 add, remove 멤버함수 추가.
SocketUtils
- CloseSocket에서 SOCKET 레퍼런스를 인자로 받게 수정.
채팅 서버 테스트
클라이언트 측 (ncat으로 접속)

서버

세션이 소멸할 때 메시지를 출력하게 만들었는데, 유저가 퇴장하면 세션이 정상적으로 소멸한다.
현재까지의 git 버전
Feat: SendRegister, broadcast 추가 · Dodontak/Project_Island_GameServer@3d413f0
RecvBuffer, sendBuffer 클래스 추가 - authserver에서 그대로 가져옴 (변경 필요할 수 있음) Session - 기존 BYTE배열 버퍼를 sendBufferQueue로 변경 - 기존 BYTE배열 버퍼를 RecvBuffer로 변경 - 각종 recv, send, connect, di
github.com
처음에 싱글스레드로 어느정도 만든 다음에 멀티스레드로 전환하려 했는데, 이번에 만들면서 멀티스레드로 가려면 처음부터 멀티스레드로 가는게 나은 것 같다고 느꼈다. 만들면서 "이 부분은 멀티스레드 고려하려면 락을 걸어야겠는데?" "이 변수는 atomic으로 만들어야 할 것 같은데?" 싶은 경우가 상당히 많았는데, 그냥 넘어가니까 매우 찜찜하기도 했고, 이렇게 구현을 잔뜩 하면서 구멍을 잔뜩 놔두고 넘어간 다음에서 멀티스레드로 바꾸려 하면 뭔가 하나쯤 실수로 놓칠 것 같다는 것.
그런 관계로 원래는 다음에 지금까지 다소 난잡하게 만들어놓은걸 깔끔하게 정리하는 시간을 가져보려 했는데, 대신에 멀티스레드를 먼저 추가하고, 정리는 그 다음에 하기로 하자.
이번 작업을 하면서 겪은 어려움(삽질) 기록
IocpEvent가 OVERLAPPED를 상속받아서 GetQueueCompletionStatus 에서 돌려받도록 만들었는데, 왜인지 AcceptEx에서 넣을때의 IocpEvent* 주소와 돌려받는 IocpEvent* 주소가 8 차이가났다. 주소를 줄때 잘못 주는건가? 하고 몇번이나 전체적으로 확인해봤는데도 한참동안 문제를 못찾다가 원인을 찾았는데, IocpEvent에 virtual 함수를 하나 넣어놨던 것이 문제였다. 가상함수때문에 가상함수 테이블 포인터가 상속받은 OVERLAPPED의 데이터보다 앞에 있어서 넣을때 주소와 꺼낼 때 주소에 뭔가 차이가 있었던 것.
해결하려면 가상함수를 빼버리거나, GetQueueCompletionStatus에서 받을 때 IocpEvent*로 받지 않고 Overlapped*로 받은 다음 static_cast로 변환해주면 된다(후자는 안해봐서 확실하진 않음). 나는 그냥 버추얼함수가 꼭 필요한건 아니었기 때문에 그냥 빼버렸다.
'프로젝트 > Project_Island' 카테고리의 다른 글
| 30. Connect, Disconnect 구현 (0) | 2026.03.31 |
|---|---|
| 29. 멀티스레드 구현, Partial Send 문제 해결 (0) | 2026.03.30 |
| 27. IOCP accept, recv까지 구현 (0) | 2026.03.28 |
| 26. NetAddress (0) | 2026.03.27 |
| 25. SocketUtils (0) | 2026.03.26 |