@@ -80,20 +80,17 @@ bool IOCP_Server::StartServer()
80
80
return true ;
81
81
}
82
82
83
- void IOCP_Server::initClient (std::list< class PLAYER *>& player )
83
+ void IOCP_Server::initClient ()
84
84
{
85
- // 플레이어 데이터를 미리 추가해 놓는다.
86
- for (int i = 0 ; i < MAX_PLAYER; ++i) {
87
- PLAYER * tmp_player = new PLAYER;
88
- tmp_player->set_init_player ();
89
- player.push_back (tmp_player);
90
- }
85
+ // 미리 player, player_session 공간을 할당 한다.
86
+ player_session.reserve (MAX_PLAYER);
87
+ player.reserve (MAX_PLAYER);
91
88
92
89
// 세션 데이터도 미리 추가해 놓는다.
93
90
for (int i = 0 ; i < MAX_PLAYER; ++i) {
94
- PLAYER_Session * tmp_session = new PLAYER_Session;
95
- tmp_session ->set_init_session ();
96
- player_session.push_back (tmp_session );
91
+ PLAYER_Session * pPlayerSession = new PLAYER_Session;
92
+ pPlayerSession ->set_init_session ();
93
+ player_session.push_back (pPlayerSession );
97
94
}
98
95
}
99
96
@@ -137,7 +134,7 @@ bool IOCP_Server::CreateWokerThread()
137
134
void IOCP_Server::WokerThread ()
138
135
{
139
136
// CompletionKey를 받을 포인터 변수
140
- PLAYER_Session* pClientInfo = NULL ;
137
+ PLAYER_Session* pPlayerSession = NULL ;
141
138
// 함수 호출 성공 여부
142
139
BOOL bSuccess = TRUE ;
143
140
// Overlapped I/O작업에서 전송된 데이터 크기
@@ -157,7 +154,7 @@ void IOCP_Server::WokerThread()
157
154
// ////////////////////////////////////////////////////
158
155
bSuccess = GetQueuedCompletionStatus (g_hiocp,
159
156
&dwIoSize, // 실제로 전송된 바이트
160
- (PULONG_PTR)&pClientInfo , // CompletionKey
157
+ (PULONG_PTR)&pPlayerSession , // CompletionKey
161
158
&lpOverlapped, // Overlapped IO 객체
162
159
INFINITE); // 대기할 시간
163
160
@@ -176,8 +173,9 @@ void IOCP_Server::WokerThread()
176
173
// client가 접속을 끊었을때..
177
174
if (FALSE == bSuccess || (0 == dwIoSize && TRUE == bSuccess))
178
175
{
179
- std::cout << " [" << (int )pClientInfo->get_unique_id () << " ]" << " Socket 접속 끊김..." << std::endl;
180
- CloseSocket (pClientInfo);
176
+ std::cout << " [" << (int )pPlayerSession->get_unique_id () << " ] Socket 접속 끊김..." << std::endl;
177
+ ClosePlayer (pPlayerSession->get_unique_id ());
178
+ CloseSocket (pPlayerSession);
181
179
continue ;
182
180
}
183
181
@@ -197,9 +195,12 @@ void IOCP_Server::WokerThread()
197
195
t->event = T_NormalTime;
198
196
timer.setTimerEvent (*t);
199
197
// ----------------------------------------------------
200
- // 클라이언트에 메세지를 에코한다.
201
- /* SendMsg(pClientInfo, pOverlappedEx->m_szBuf, dwIoSize);
202
- BindRecv(pClientInfo);*/
198
+ // 클라이언트에 메세지를 에코한다. 'kch'일 경우에만 리턴을 하도록 하였다.
199
+ if (!strcmp (pOverlappedEx->m_szBuf , " kch" )) {
200
+ SendMsg (pPlayerSession, pOverlappedEx->m_szBuf , dwIoSize);
201
+ BindRecv (pPlayerSession);
202
+ }
203
+
203
204
}
204
205
break ;
205
206
case IOOperation::SEND:
@@ -219,7 +220,7 @@ void IOCP_Server::WokerThread()
219
220
}
220
221
}
221
222
222
- void IOCP_Server::CloseSocket (PLAYER_Session * pClientInfo , bool bIsForce)
223
+ void IOCP_Server::CloseSocket (PLAYER_Session * pPlayerSession , bool bIsForce)
223
224
{
224
225
struct linger stLinger = { 0 , 0 }; // SO_DONTLINGER로 설정
225
226
@@ -230,14 +231,49 @@ void IOCP_Server::CloseSocket(PLAYER_Session * pClientInfo, bool bIsForce)
230
231
}
231
232
232
233
// socketClose소켓의 데이터 송수신을 모두 중단 시킨다.
233
- shutdown (pClientInfo ->m_socketSession , SD_BOTH);
234
+ shutdown (pPlayerSession ->m_socketSession , SD_BOTH);
234
235
235
236
// 소켓 옵션을 설정한다.
236
- setsockopt (pClientInfo ->m_socketSession , SOL_SOCKET, SO_LINGER, (char *)&stLinger, sizeof (stLinger));
237
+ setsockopt (pPlayerSession ->m_socketSession , SOL_SOCKET, SO_LINGER, (char *)&stLinger, sizeof (stLinger));
237
238
238
239
// 소켓 연결을 종료 시킨다.
239
- closesocket (pClientInfo->m_socketSession );
240
- pClientInfo->m_socketSession = INVALID_SOCKET;
240
+ closesocket (pPlayerSession->m_socketSession );
241
+ pPlayerSession->m_socketSession = INVALID_SOCKET;
242
+ }
243
+
244
+ void IOCP_Server::ClosePlayer (unsigned __int64 uniqueId)
245
+ {
246
+ player.erase (uniqueId);
247
+ }
248
+
249
+ bool IOCP_Server::SendMsg (PLAYER_Session * pPlayerSession, char * pMsg, int nLen)
250
+ {
251
+ DWORD dwRecvNumBytes = 0 ;
252
+
253
+ // 전송될 메세지를 복사
254
+ CopyMemory (pPlayerSession->get_Send_over ().m_szBuf , pMsg, nLen);
255
+
256
+
257
+ // Overlapped I/O을 위해 각 정보를 셋팅해 준다.
258
+ pPlayerSession->get_Send_over ().m_wsaBuf .len = nLen;
259
+ pPlayerSession->get_Send_over ().m_wsaBuf .buf = pPlayerSession->get_Send_over ().m_szBuf ;
260
+ pPlayerSession->get_Send_over ().m_eOperation = IOOperation::SEND;
261
+
262
+ int nRet = WSASend (pPlayerSession->m_socketSession ,
263
+ &(pPlayerSession->get_Send_over ().m_wsaBuf ),
264
+ 1 ,
265
+ &dwRecvNumBytes,
266
+ 0 ,
267
+ (LPWSAOVERLAPPED) & (pPlayerSession->get_Send_over ()),
268
+ NULL );
269
+
270
+ // socket_error이면 client socket이 끊어진걸로 처리한다.
271
+ if (nRet == SOCKET_ERROR && (WSAGetLastError () != ERROR_IO_PENDING))
272
+ {
273
+ std::cout << " [Error] WSASend()함수 실패..! " << WSAGetLastError () << std::endl;
274
+ return false ;
275
+ }
276
+ return true ;
241
277
}
242
278
243
279
bool IOCP_Server::CreateAccepterThread ()
@@ -257,36 +293,45 @@ void IOCP_Server::AccepterThread()
257
293
while (mIsAccepterRun )
258
294
{
259
295
// 접속을 받을 구조체의 인덱스를 얻어온다.
260
- PLAYER_Session* pClientInfo = GetEmptySession ();
261
- if (NULL == pClientInfo ) {
296
+ PLAYER_Session* pPlayerSession = GetEmptySession ();
297
+ if (NULL == pPlayerSession ) {
262
298
std::cout << " [Error] Client Full..!" << std::endl;
263
299
return ;
264
300
}
265
301
266
302
// 클라이언트 접속 요청이 들어올 때까지 기다린다.
267
- pClientInfo ->m_socketSession = WSAAccept (listenSocket, reinterpret_cast <sockaddr *>(&client_addr), &client_len, NULL , NULL );
268
- if (INVALID_SOCKET == pClientInfo ->m_socketSession ) {
303
+ pPlayerSession ->m_socketSession = WSAAccept (listenSocket, reinterpret_cast <sockaddr *>(&client_addr), &client_len, NULL , NULL );
304
+ if (INVALID_SOCKET == pPlayerSession ->m_socketSession ) {
269
305
continue ;
270
306
}
271
307
272
308
// I/O Completion Port객체와 소켓을 연결시킨다.
273
- bool bRet = BindIOCompletionPort (pClientInfo );
309
+ bool bRet = BindIOCompletionPort (pPlayerSession );
274
310
if (false == bRet) {
275
311
return ;
276
312
}
277
313
278
- // Recv Overlapped I/O작업을 요청해 놓는다.
279
- bRet = BindRecv (pClientInfo );
314
+ // Recv Overlapped I/O작업을 요청해 놓는다.
315
+ bRet = BindRecv (pPlayerSession );
280
316
if (false == bRet) {
281
317
return ;
282
318
}
283
319
320
+ // session에 set 해준다.
321
+ pPlayerSession->set_unique_id (uniqueId);
322
+
323
+ // 플레이어를 set 해준다.
324
+ class PLAYER * acceptPlayer = new class PLAYER ;
325
+ acceptPlayer->set_sock (pPlayerSession->m_socketSession );
326
+ acceptPlayer->set_unique_id (uniqueId);
327
+ player.insert (std::unordered_map<unsigned __int64, class PLAYER *>::value_type (uniqueId, acceptPlayer));
328
+
284
329
// 클라이언트 갯수 증가
285
330
++uniqueId;
286
331
287
332
char clientIP[32 ] = { 0 , };
288
333
inet_ntop (AF_INET, &(client_addr.sin_addr ), clientIP, 32 - 1 );
289
- std::cout << " [접속(" << uniqueId << " )] Client IP : " << clientIP << " / SOCKET : " << (int )pClientInfo ->m_socketSession << std::endl;
334
+ std::cout << " [접속(" << uniqueId << " )] Client IP : " << clientIP << " / SOCKET : " << (int )pPlayerSession ->m_socketSession << std::endl;
290
335
291
336
292
337
}
@@ -303,10 +348,10 @@ PLAYER_Session* IOCP_Server::GetEmptySession()
303
348
return nullptr ;
304
349
}
305
350
306
- bool IOCP_Server::BindIOCompletionPort (PLAYER_Session * pClientInfo )
351
+ bool IOCP_Server::BindIOCompletionPort (PLAYER_Session * pPlayerSession )
307
352
{
308
- // socket과 pClientInfo를 CompletionPort객체와 연결시킨다.
309
- auto hIOCP = CreateIoCompletionPort ((HANDLE)pClientInfo ->m_socketSession , g_hiocp, (ULONG_PTR)(pClientInfo ), 0 );
353
+ // socket과 pPlayerSession를 CompletionPort객체와 연결시킨다.
354
+ auto hIOCP = CreateIoCompletionPort ((HANDLE)pPlayerSession ->m_socketSession , g_hiocp, (ULONG_PTR)(pPlayerSession ), 0 );
310
355
311
356
if (NULL == hIOCP || g_hiocp != hIOCP) {
312
357
std::cout << " [Error] CreateIoCompletionPort()함수 실패 : " << GetLastError () << std::endl;
@@ -316,22 +361,22 @@ bool IOCP_Server::BindIOCompletionPort(PLAYER_Session * pClientInfo)
316
361
return true ;
317
362
}
318
363
319
- bool IOCP_Server::BindRecv (PLAYER_Session * pClientInfo )
364
+ bool IOCP_Server::BindRecv (PLAYER_Session * pPlayerSession )
320
365
{
321
366
DWORD dwFlag = 0 ;
322
367
DWORD dwRecvNumBytes = 0 ;
323
368
324
369
// Overlapped I/O을 위해 각 정보를 셋팅해 준다.
325
- pClientInfo ->get_Recv_over ().m_wsaBuf .len = MAX_SOCKBUF;
326
- pClientInfo ->get_Recv_over ().m_wsaBuf .buf = pClientInfo ->get_Recv_over ().m_szBuf ;
327
- pClientInfo ->get_Recv_over ().m_eOperation = IOOperation::RECV;
370
+ pPlayerSession ->get_Recv_over ().m_wsaBuf .len = MAX_SOCKBUF;
371
+ pPlayerSession ->get_Recv_over ().m_wsaBuf .buf = pPlayerSession ->get_Recv_over ().m_szBuf ;
372
+ pPlayerSession ->get_Recv_over ().m_eOperation = IOOperation::RECV;
328
373
329
- int nRet = WSARecv (pClientInfo ->m_socketSession ,
330
- &(pClientInfo ->get_Recv_over ().m_wsaBuf ),
374
+ int nRet = WSARecv (pPlayerSession ->m_socketSession ,
375
+ &(pPlayerSession ->get_Recv_over ().m_wsaBuf ),
331
376
1 ,
332
377
&dwRecvNumBytes,
333
378
&dwFlag,
334
- (LPWSAOVERLAPPED) & (pClientInfo ->get_Recv_over ()),
379
+ (LPWSAOVERLAPPED) & (pPlayerSession ->get_Recv_over ()),
335
380
NULL );
336
381
337
382
// socket_error이면 client socket이 끊어진걸로 처리한다.
0 commit comments