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를 사용하는 모든 코드에서 새로 작성한 클래스에 맞게 수정했다.

+ Recent posts