자잘한 수정, 이제 다른 소켓으로 쓰기 요청 할 수 있을 듯

This commit is contained in:
2025-05-03 13:59:04 +09:00
parent 181d30ff28
commit f765c163bf
12 changed files with 512 additions and 310 deletions

View File

@@ -1,11 +1,81 @@
#pragma once
#include "Utils/ThreadPool.hpp"
#include "Utils/ConfigManager.hpp"
#include "Socket/IOCP.hpp"
#include "Packet/Packet.hpp"
namespace Chattr {
class ServerManager {
public:
void init();
void
void _IOCPClient(ThreadPool* thread, IOCPPASSINDATA* data);
PacketSet packetParser(Packet Packet);
template<typename _Callable>
void init(_Callable _IOCPClient) {
auto config = ConfigManager::load();
log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount);
threadPool_.init(0);
iocp_.init(&threadPool_, _IOCPClient);
struct Address serveraddr;
if (config.ipVersion == 4) {
listenSock_.init(AF_INET);
serveraddr.set(AF_INET, INADDR_ANY, config.listenPort);
clientAddr_.setType(AF_INET);
}
else if (config.ipVersion == 6) {
listenSock_.init(AF_INET6);
serveraddr.set(AF_INET6, in6addr_any, config.listenPort);
clientAddr_.setType(AF_INET6);
}
listenSock_.bind(serveraddr);
listenSock_.listen(SOMAXCONN);
}
void init() {
init([this](ThreadPool* thread, IOCPPASSINDATA* data) {
_IOCPClient(thread, data);
});
}
void registerUser(std::string userName, std::shared_ptr<TCPSocket> sock);
void deleteUser(Snowflake UID);
std::vector<std::pair<Snowflake, std::string>> getUserList();
void createRoom(std::string roomName);
void deleteRoom(Snowflake RID);
std::vector<std::pair<Snowflake, std::string>> getRoomList();
void joinRoom(Snowflake UID, Snowflake RID);
void exitRoom(Snowflake UID, Snowflake RID);
Snowflake generateID();
void run();
private:
ThreadPool threadPool_;
IOCP iocp_;
TCPSocket listenSock_;
TCPSocket clientSock_;
struct Address clientAddr_;
std::mutex resourceMutex_;
std::mutex snowflakeGenerateMutex_;
std::unordered_map<Snowflake, std::string> roomNames_;
std::unordered_map<Snowflake, std::unordered_map<Snowflake, std::shared_ptr<TCPSocket>>> rooms_;
std::unordered_map<Snowflake, std::shared_ptr<TCPSocket>> UID2userSocket_;
std::unordered_map<TCPSocket*, Snowflake> userSocket2UID_;
std::unordered_map<Snowflake, std::string> userNames_;
};
}

View File

@@ -0,0 +1,250 @@
#include "ServerManager/ServerManager.hpp"
#include "Utils/ConfigManager.hpp"
#include "Socket/Log.hpp"
namespace Chattr {
void ServerManager::_IOCPClient(Chattr::ThreadPool* thread, Chattr::IOCPPASSINDATA* data) {
Chattr::Packet pack;
int packetSize = data->transfrredbytes;
if (data->recvbytes == 0) {
data->recvbytes = data->transfrredbytes;
data->transfrredbytes = 0;
}
else if (data->transfrredbytes <= data->sendbytes) {
data->IOCPInstance->recv(data, 1);
return;
}
memcpy(pack.serialized, data->wsabuf.buf, data->wsabuf.len);
pack.convToH();
std::string recvString;
bool packetError = false;
DataPostPacket dataPostPacket;
ResponsePacket responsePacket;
LoginRequestPacket loginRequestPacket;
switch (packetParser(pack)) {
case PacketSet::LOGINREQUEST:
break;
case PacketSet::ROOMCREATEREQUEST:
break;
case PacketSet::ROOMLISTREQUEST:
break;
case PacketSet::ROOMJOINREQUEST:
break;
case PacketSet::ROOMEXITREQUEST:
break;
case PacketSet::USERSLISTREQUEST:
break;
case PacketSet::DATAPOSTTEXT:
std::memcpy(&dataPostPacket.serialized, &pack, 1500);
dataPostPacket.__data.packetLength = (dataPostPacket.__data.packetLength > 1487) ? 1487 : dataPostPacket.__data.packetLength;
recvString = std::string((char*)dataPostPacket.__data.data, dataPostPacket.__data.packetLength - (sizeof(std::uint16_t) * 4));
spdlog::info("Received [{}] from : [{}]", recvString, (std::string)data->socket->remoteAddr);
responsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE;
responsePacket.__data.requestType = Chattr::RequestType::DATA;
responsePacket.__data.dataType = Chattr::DataType::TEXT;
responsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode);
responsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST;
responsePacket.convToN();
memcpy(data->wsabuf.buf, responsePacket.serialized, responsePacket.__data.packetLength + 8);
// data->sendbytes = responsePacket.__data.packetLength + 5;
data->sendbytes = 1500;
data->IOCPInstance->send(data, 1, 0);
break;
case PacketSet::DATAPOSTBINARY:
break;
case PacketSet::CONTINUE:
break;
case PacketSet::INVALID:
default:
responsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE;
responsePacket.__data.requestType = Chattr::RequestType::DATA;
responsePacket.__data.dataType = Chattr::DataType::TEXT;
responsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode);
responsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST;
responsePacket.convToN();
memcpy(data->wsabuf.buf, responsePacket.serialized, responsePacket.__data.packetLength + 8);
// data->sendbytes = responsePacket.__data.packetLength + 5;
data->sendbytes = responsePacket.__data.packetLength + 8;
data->transfrredbytes = responsePacket.__data.packetLength + 8;
data->IOCPInstance->send(data, 1, 0);
break;
}
}
PacketSet ServerManager::packetParser(Packet Packet) {
if (Packet.__data.packetLength < 0 || Packet.__data.packetLength > 1500)
return PacketSet::INVALID;
switch (Packet.__data.packetType) {
case PacketCategory::PACKET_POST:
if (Packet.__data.requestType != RequestType::DATA) {
return PacketSet::INVALID;
}
switch (Packet.__data.dataType) {
case DataType::TEXT:
return PacketSet::DATAPOSTTEXT;
case DataType::BINARY:
return PacketSet::DATAPOSTBINARY;
default:
return PacketSet::INVALID;
}
break;
case PacketCategory::PACKET_REQUEST:
switch (Packet.__data.requestType) {
case RequestType::LOGIN:
return PacketSet::LOGINREQUEST;
case RequestType::ROOM_CREATE:
return PacketSet::ROOMCREATEREQUEST;
case RequestType::ROOM_LIST:
return PacketSet::ROOMLISTREQUEST;
case RequestType::ROOM_JOIN:
return PacketSet::ROOMJOINREQUEST;
case RequestType::ROOM_EXIT:
return PacketSet::ROOMEXITREQUEST;
case RequestType::USERS_LIST:
return PacketSet::USERSLISTREQUEST;
case RequestType::DATA:
return PacketSet::INVALID;
}
break;
case PacketCategory::PACKET_RESPONSE:
switch (Packet.__data.requestType) {
case RequestType::LOGIN:
return PacketSet::LOGINRESPONSE;
case RequestType::ROOM_CREATE:
return PacketSet::ROOMCREATERESPONSE;
case RequestType::ROOM_LIST:
return PacketSet::ROOMLISTRESPONSE;
case RequestType::ROOM_JOIN:
return PacketSet::ROOMJOINRESPONSE;
case RequestType::ROOM_EXIT:
return PacketSet::ROOMEXITRESPONSE;
case RequestType::USERS_LIST:
return PacketSet::USERSLISTRESPONSE;
case RequestType::DATA:
return PacketSet::INVALID;
}
break;
case PacketCategory::PACKET_CONTINUE:
return PacketSet::CONTINUE;
default:
return PacketSet::INVALID;
}
}
void ServerManager::registerUser(std::string userName, std::shared_ptr<TCPSocket> sock) {
std::lock_guard<std::mutex> lock(resourceMutex_);
Snowflake UID = generateID();
userNames_[UID] = userName;
UID2userSocket_[UID] = sock;
userSocket2UID_[sock.get()] = UID;
}
void ServerManager::deleteUser(Snowflake UID) {
std::lock_guard<std::mutex> lock(resourceMutex_);
userNames_.erase(UID);
std::shared_ptr<TCPSocket> sock = UID2userSocket_[UID];
UID2userSocket_.erase(UID);
userSocket2UID_.erase(sock.get());
}
std::vector<std::pair<Snowflake, std::string>> ServerManager::getUserList() {
std::lock_guard<std::mutex> lock(resourceMutex_);
std::vector<std::pair<Snowflake, std::string>> userList;
userList.reserve(userNames_.size());
for (auto user : userNames_)
userList.push_back(user);
return userList;
}
void ServerManager::createRoom(std::string roomName) {
std::lock_guard<std::mutex> lock(resourceMutex_);
Snowflake RID = generateID();
roomNames_[RID] = roomName;
rooms_[RID] = std::unordered_map<Snowflake, std::shared_ptr<TCPSocket>>();
}
void ServerManager::deleteRoom(Snowflake RID) {
std::lock_guard<std::mutex> lock(resourceMutex_);
roomNames_.erase(RID);
rooms_.erase(RID);
}
std::vector<std::pair<Snowflake, std::string>> ServerManager::getRoomList() {
std::lock_guard<std::mutex> lock(resourceMutex_);
std::vector<std::pair<Snowflake, std::string>> roomList;
roomList.reserve(roomNames_.size());
for (auto user : roomNames_)
roomList.push_back(user);
return roomList;
}
void ServerManager::joinRoom(Snowflake UID, Snowflake RID) {
std::lock_guard<std::mutex> lock(resourceMutex_);
std::shared_ptr<TCPSocket> sock = UID2userSocket_[UID];
rooms_[RID][UID] = sock;
}
void ServerManager::exitRoom(Snowflake UID, Snowflake RID) {
std::lock_guard<std::mutex> lock(resourceMutex_);
rooms_[RID].erase(UID);
}
static struct _EPOCH {
_EPOCH() {
EPOCH = std::chrono::system_clock::now();
}
std::chrono::system_clock::time_point EPOCH;
} __EPOCH__;
Snowflake ServerManager::generateID() {
std::lock_guard<std::mutex> lock(snowflakeGenerateMutex_);
#ifdef _WIN32
DWORD tid = GetCurrentThreadId();
#elif __linux__
pthread_t tid = pthread_self();
#endif
static int sequence = 0;
Snowflake id = {};
auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - __EPOCH__.EPOCH);
id.timestamp = timestamp.count();
id.instance = tid;
id.sequence = sequence++;
return id;
}
void ServerManager::run() {
while (true) {
spdlog::info("Waiting for connection...");
listenSock_.accept(clientSock_, clientAddr_);
bool enable = true;
clientSock_.setsockopt(SOL_SOCKET, SO_KEEPALIVE, (const char*)&enable, sizeof(enable));
Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA;
::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED));
ptr->socket = std::make_shared<TCPSocket>(std::move(clientSock_));
ptr->recvbytes = ptr->sendbytes = 0;
ptr->wsabuf.buf = ptr->buf;
ptr->wsabuf.len = 1500;
ptr->IOCPInstance = &iocp_;
iocp_.registerSocket(ptr);
int returnData = iocp_.recv(ptr, 1);
}
}
}

View File

@@ -1,194 +1,9 @@
#include "Socket/TCPSocket.hpp"
#include "Socket/Log.hpp"
#include "Socket/WSAManager.hpp"
#include "Utils/ConfigManager.hpp"
#include "Utils/Thread.hpp"
#include "Utils/ThreadPool.hpp"
#include "Utils/StringTokenizer.hpp"
#include "Utils/Snowflake.hpp"
#include "Socket/IOCP.hpp"
#include "Packet/Packet.hpp"
#include <iostream>
#include <bitset>
#include "ServerManager/ServerManager.hpp"
#include "precomp.hpp"
void _IOCPClient(Chattr::ThreadPool* threadPool, Chattr::IOCPPASSINDATA* data);
void _TCPSendClient(Chattr::ThreadPool* threadPool, Chattr::TCPSocket sock, std::queue<Chattr::ResponsePacket> packets);
int main() {
auto config = Chattr::ConfigManager::load();
Chattr::log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount);
Chattr::ThreadPool threadPool(0);
Chattr::IOCP iocp;
iocp.init(&threadPool, _IOCPClient);
Chattr::TCPSocket sock;
struct Chattr::Address serveraddr;
Chattr::TCPSocket clientSock;
struct Chattr::Address clientAddr;
if (config.ipVersion == 4) {
sock.init(AF_INET);
serveraddr.set(AF_INET, INADDR_ANY, config.listenPort);
clientAddr.setType(AF_INET);
}
else if (config.ipVersion == 6) {
sock.init(AF_INET6);
serveraddr.set(AF_INET6, in6addr_any, config.listenPort);
clientAddr.setType(AF_INET6);
}
sock.bind(serveraddr);
sock.listen(SOMAXCONN);
#ifdef _WIN32
DWORD pid = GetCurrentProcessId();
#elif __linux__
pid_t pid = getpid();
#endif
spdlog::debug("PID : {}", pid);
while (true) {
spdlog::info("Waiting for connection...");
sock.accept(clientSock, clientAddr);
bool enable = true;
clientSock.setsockopt(SOL_SOCKET, SO_KEEPALIVE, (const char *)&enable, sizeof(enable));
Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA;
::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED));
ptr->socket = std::move(clientSock);
ptr->recvbytes = ptr->sendbytes = 0;
ptr->wsabuf.buf = ptr->buf;
ptr->wsabuf.len = 1500;
ptr->IOCPInstance = &iocp;
iocp.registerSocket(ptr);
int returnData = iocp.recv(ptr);
}
}
void _IOCPClient(Chattr::ThreadPool* thread, Chattr::IOCPPASSINDATA* data) {
Chattr::Packet pack;
int packetSize = 1500;
int totalRedSize = 0;
int redSize = 0;
if (data->wsabuf.len == data->sendbytes)
return;
memcpy(pack.serialized, data->wsabuf.buf, data->wsabuf.len);
std::string recvString;
bool packetError = false;
Chattr::DataPostPacket dataPostPacket;
Chattr::ResponsePacket packet;
std::queue<Chattr::ResponsePacket> responsePackets;
switch (pack.__data.packetType) {
case Chattr::PacketType::PACKET_POST:
if (pack.__data.requestType != Chattr::RequestType::DATA){
packetError = true;
break;
}
switch (pack.__data.dataType) {
case Chattr::DataType::TEXT:
std::memcpy(&dataPostPacket.serialized, &pack, 1500);
dataPostPacket.convToH();
dataPostPacket.__data.packetLength = (dataPostPacket.__data.packetLength > 1487) ? 1487 : dataPostPacket.__data.packetLength;
recvString = std::string((char *)dataPostPacket.__data.data, dataPostPacket.__data.packetLength - (sizeof(std::uint16_t)*4));
spdlog::info("Red size : {}, {} from : [{}]", data->wsabuf.len, recvString, (std::string)data->socket.remoteAddr);
break;
case Chattr::DataType::BINARY:
break;
default:
packet.__data.packetType = Chattr::PacketType::PACKET_RESPONSE;
packet.__data.requestType = Chattr::RequestType::DATA;
packet.__data.dataType = Chattr::DataType::TEXT;
packet.__data.packetLength = sizeof(Chattr::ResponseStatusCode);
packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST;
packet.convToN();
responsePackets.push(packet);
packetError = true;
break;
}
break;
case Chattr::PacketType::PACKET_REQUEST:
switch (pack.__data.requestType) {
case Chattr::RequestType::LOGIN:
break;
case Chattr::RequestType::ROOM_CREATE:
break;
case Chattr::RequestType::ROOM_LIST:
break;
case Chattr::RequestType::ROOM_JOIN:
break;
case Chattr::RequestType::ROOM_EXIT:
break;
case Chattr::RequestType::USERS_LIST:
break;
default:
packet.__data.packetType = Chattr::PacketType::PACKET_RESPONSE;
packet.__data.requestType = Chattr::RequestType::DATA;
packet.__data.dataType = Chattr::DataType::TEXT;
packet.__data.packetLength = sizeof(Chattr::ResponseStatusCode);
packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST;
packet.convToN();
responsePackets.push(packet);
packetError = true;
break;
}
break;
case Chattr::PacketType::PACKET_CONTINUE:
break;
default:
packet.__data.packetType = Chattr::PacketType::PACKET_RESPONSE;
packet.__data.requestType = Chattr::RequestType::DATA;
packet.__data.dataType = Chattr::DataType::TEXT;
packet.__data.packetLength = sizeof(Chattr::ResponseStatusCode);
packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST;
packet.convToN();
responsePackets.push(packet);
packetError = true;
break;
}
packet.__data.packetType = Chattr::PacketType::PACKET_RESPONSE;
packet.__data.requestType = Chattr::RequestType::DATA;
packet.__data.dataType = Chattr::DataType::TEXT;
packet.__data.packetLength = sizeof(Chattr::ResponseStatusCode);
packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST;
packet.convToN();
memcpy(data->wsabuf.buf, packet.serialized, data->wsabuf.len);
int returnData = data->IOCPInstance->send(data, 0);
// int returnData = data->IOCPInstance->recv(data);
}
void _TCPSendClient(Chattr::ThreadPool* thread, Chattr::TCPSocket sock, std::queue<Chattr::ResponsePacket> packets) {
Chattr::ResponsePacket pack = packets.front();
packets.pop();
int packetSize = 1500;
int totalSentSize = 0;
int sentSize = 0;
spdlog::info("Sending to: [{}]", (std::string)sock.remoteAddr);
while (totalSentSize < packetSize) {
sentSize = sock.send(&pack.serialized, 1500 - totalSentSize, 0);
if (sentSize <= 0) {
spdlog::info("Client disconnected. [{}]", (std::string)sock.remoteAddr);
return;
}
totalSentSize += sentSize;
}
/*if (packets.empty())
thread->enqueueJob(_TCPRecvClient, std::move(sock));
else
thread->enqueueJob(_TCPSendClient, std::move(sock), packets);*/
Chattr::ServerManager server;
server.init();
server.run();
}