-
Notifications
You must be signed in to change notification settings - Fork 0
/
Client.cpp
124 lines (116 loc) · 3.58 KB
/
Client.cpp
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//
// Created by floweryclover on 2024-01-27.
//
#include "Client.h"
#include "Message.h"
#include "Context.h"
#include "CtsRpc.h"
#include "BattleGameServer.h"
#include "ClientManager.h"
#include <iostream>
#include <utility>
#include <memory>
#include <cstring>
#ifdef _WIN32
#include <WinSock2.h>
#elifdef linux
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cerrno>
#endif
Client::Client(ClientId clientId, Socket&& tcpSocket, SocketAddress&& tcpSocketAddress) noexcept
: mClientId(clientId),
mTcpSocket(std::move(tcpSocket)),
mIsReceivingHeader(true),
mCurrentReceived(0),
mTotalSizeToReceive(HEADER_SIZE),
mLastReceivedHeaderType(0),
mTcpSocketAddress(std::move(tcpSocketAddress))
{}
Client::Client(Client&& rhs) noexcept : Client(rhs.mClientId, const_cast<Socket&&>(std::move(rhs.mTcpSocket)), std::move(rhs.mTcpSocketAddress)) {}
Client::~Client() {}
void Client::Tick()
{
auto receiveResult = this->ReceiveTcp();
if (receiveResult.has_value())
{
if (receiveResult.value().has_value())
{
Context context(mClientId, SendReliability::RELIABLE);
BattleGameServer::GetConstInstance()
.GetConstCtsRpc()
.HandleMessage(context, *receiveResult.value().value());
}
}
else
{
if (receiveResult.error().has_value())
{
std::cerr << "[에러] 클라이언트 " << mClientId << " 에게서 데이터를 수신하던 도중 에러가 발생하였습니다: 에러 코드 " << receiveResult.error().value() << "." << std::endl;
}
BattleGameServer::GetInstance()
.GetClientManager()
.InvokeOnPlayerDisconnected(mClientId);
}
}
std::expected<std::optional<std::unique_ptr<Message>>, std::optional<ErrorCode>> Client::ReceiveTcp() {
int sizeToReceive = mTotalSizeToReceive - mCurrentReceived;
int result = recv(GetTcpSocket().GetRawHandle(), mReceiveBuffer.data() + mCurrentReceived, sizeToReceive, 0);
if (result == -1)
{
#ifdef _WIN32
int errorCode = WSAGetLastError();
if (errorCode == WSAEWOULDBLOCK)
#elifdef linux
int errorCode = errno;
if (errorCode == EWOULDBLOCK)
#endif
{
return std::nullopt;
}
else
{
return std::unexpected(errorCode);
}
}
else if (result == 0)
{
return std::unexpected(std::nullopt);
}
else
{
mCurrentReceived += result;
if (mCurrentReceived == mTotalSizeToReceive)
{
mCurrentReceived = 0;
if (mIsReceivingHeader)
{
memcpy(&mTotalSizeToReceive, mReceiveBuffer.data(), 4);
memcpy(&mLastReceivedHeaderType, mReceiveBuffer.data() + 4, 4);
if (mTotalSizeToReceive == 0) // 바디 없는 메시지
{
std::unique_ptr<Message> pMessage(new Message(0, mLastReceivedHeaderType, nullptr));
mTotalSizeToReceive = HEADER_SIZE;
mIsReceivingHeader = true;
return pMessage;
}
else
{
mIsReceivingHeader = false;
return std::nullopt;
}
}
else
{
std::unique_ptr<Message> pMessage(new Message(mTotalSizeToReceive, mLastReceivedHeaderType, mReceiveBuffer.data()));
mTotalSizeToReceive = HEADER_SIZE;
mIsReceivingHeader = true;
return pMessage;
}
}
else
{
return std::nullopt;
}
}
}