Session이 가지고 있는 SendQueue는 STL의 큐를 사용하기 때문에 멀티 쓰레드에서 사용하려면, 동기화 객체를 사용해야한다.
앞서 작성한 SendPacket, SendPost, SendComplete 모두 멀티 쓰레드 환경에서 사용하면 위험하다.
내부적으로 CriticalSection을 관리하며 Queue에 데이터를 넣고 빼는 클래스를 따로 준비했다.
#pragma once
#include"pch.h"
#include"Packet.h"
#define SEND_QUEUE
#ifdef SEND_QUEUE
#define SEND_QUEUE_DLL __declspec(dllexport)
#else
#define SEND_QUEUE_DLL __declspec(dllimport)
#endif
class SEND_QUEUE_DLL SendQueue
{
private:
queue<Packet*> queue;
CRITICAL_SECTION cs;
public:
SendQueue();
~SendQueue();
// packet 넣기
void Push(Packet* packet);
// packet 빼기
Packet* Pop();
// packet이 있는지 확인
bool IsEmpty();
// 내부 queue 청소
void Clear();
// queue에 있는 packet의 개수 반환
size_t Size();
};
생성자에서 CriticalSection을 초기화 하고, 소멸자에서 삭제한다.
내부 큐에 Packet을 넣고, 뺄때 CriticalSection을 이용해 동기화시켜준다.
#pragma once
#include"../Packet.h"
#include"../RingBuffer.h"
#include"../SendQueue.h"
#pragma comment(lib, "..\\x64\\Debug\\NetworkLib.lib")
struct IOBlock
{
// IO 작업 횟수를 기록해둘 변수
// Session을 사용하고 있는지에 대한 여부
LONG64 IOCount = 0;
// Release를 했는지 안했는지에 대한 여부
LONG64 IsRelease = false;
};
struct Session
{
LONG sessionId = 0;
SOCKET clientSocket; // 클라이언트 소켓
SOCKADDR_IN clientAddr; // 서버에 접속한 클라 주소
RingBuffer recvRingBuffer; // recvBuf
SendQueue sendQueue; // sendQueue
OVERLAPPED recvOverlapped = {}; // WSARecv 통지
OVERLAPPED sendOverlapped = {}; // WSASend 통지
IOBlock* IOBlock = nullptr; // Session이 사용중인지, 해제되었는지 확인
LONG isSend; // 세션에 대해 WSASend 작업을 하고 있는지 안하고 있는지 여부
vector<Packet*> sendPacket; // 전송할 패킷들을 담아둠
LONG sendPacketCount; // 전송한 패킷의 개수를 기록
};
Session 구조체에서 queue<Packet*> sendQueue 를 삭제하고 SendQueue를 추가시켰다.
Session의 sendQueue를 사용하는 모든 코드에서 새로 작성한 클래스에 맞게 수정했다.
'ChattingServer' 카테고리의 다른 글
[ChattingServer] DummyClient ( 더미 ) (1) | 2025.06.11 |
---|---|
[ChattingServer] 채팅 서버 프로토콜 (0) | 2025.06.06 |
[ChattingServer] SendComplete ( WSASend 통지 완료 처리 ) (0) | 2025.06.02 |
[ChattingServer] SendPacket, SendPost ( packet 큐잉, WSASend 걸기 ) (0) | 2025.06.02 |
[ChattingServer] RecvPost ( WSARecv 걸기 ) (0) | 2025.06.02 |