728x90
반응형
#include "MySocketError.h"
#include "MySystemError.h"
#define MAXCLIENT 100
//현재 접속한 클라이언트의 소켓 정보
SOCKET clientSockets[MAXCLIENT];
int clientCount;
//클라이언트들이 접속하면 하나씩 쓰레드가 만들어진다.
unsigned int _stdcall ThreadFunc(void* lpParameter);
//q만을 감시해서 모든 클라이언트 접속을 끊어버리겠다.
unsigned int _stdcall ThreadFuncExit(void* lpParameter);
//CRITICAL_SECTION cs;
HANDLE hMutex;
void TotalClients(void);
int _tmain(void)
{
BOOL result = FALSE;
_tsetlocale(LC_ALL, _T("korean"));
HANDLE hExit = (HANDLE)_beginthreadex(NULL, 0, ThreadFuncExit
, NULL, CREATE_ALWAYS, NULL);
//InitializeCriticalSection(&cs);
hMutex = CreateMutex(NULL, FALSE, NULL);
SOCKET serverSocket;
InitTCPServer(&serverSocket);
SOCKET clientSocket;
while (1)
{
ClientAccept(serverSocket, &clientSocket);
//EnterCriticalSection(&cs);
result = WaitForSingleObject(hMutex, INFINITE);
clientSockets[clientCount++] = clientSocket;
TotalClients();
//LeaveCriticalSection(&cs);
result = ReleaseMutex(hMutex);
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0
, ThreadFunc, (void*)&clientSocket, CREATE_ALWAYS, NULL);
if (hThread == INVALID_HANDLE_VALUE)
{
SystemErrorMsg(_T("_beginthreadex"));
break;
}
BOOL result = FALSE;
result = CloseHandle(hThread);
}
//DeleteCriticalSection(&cs);
CloseHandle(hMutex);
DestroyTCPServer(serverSocket);
CloseHandle(hExit);
return 0;
}
unsigned int _stdcall ThreadFunc(void* lpParameter)
{
SOCKET clientSocket = *(SOCKET*)lpParameter;
BOOL systemError = FALSE;
int result = -1;
char buffer[BUFSIZE] = { 0 };
while (1)
{
ZeroMemory(buffer, BUFSIZE);
result = recv(clientSocket, buffer, BUFSIZE, 0);
if (!result) break;
else if (result == SOCKET_ERROR)
{
//10053은 로컬에서 소켓이 종료됨, 10054는 원격에서 소켓이 종료
if (WSAGetLastError() != 10053 && WSAGetLastError() != 10054)
//_tprintf(_T("%d\n"), WSAGetLastError());
ErrorMsg(_T("recv"));
break;
}
result = send(clientSocket, buffer, BUFSIZE, 0);
if (result == SOCKET_ERROR)
{
ErrorMsg(_T("send"));
break;
}
}
//EnterCriticalSection(&cs);
BOOL result1 = WaitForSingleObject(hMutex, INFINITE);
for (int i = 0; i < clientCount; i++)
{
if (clientSockets[i] == clientSocket)
{
for (int j = i; j < clientCount - 1; j++)
clientSockets[j] = clientSockets[j + 1];
clientCount--; //데이터 삭제하는 배열
ClientClose(clientSocket);
TotalClients(); //삭제 되었는지 확인하는 함수
break;
}
}
//LeaveCriticalSection(&cs);
result1 = ReleaseMutex(hMutex);
return 0;
}
void TotalClients(void)
{
int result = -1;
if (clientCount == 0)
{
_tprintf(_T("현재 접속된 클라이언트가 없습니다.\n"));
return;
}
_tprintf(_T("-----------------------------------------\n"));
_tprintf(_T("현재 접속된 클라이언트의 IP/PORT 정보\n"));
_tprintf(_T("-----------------------------------------\n"));
for (int i = 0; i < clientCount; i++)
{
SOCKADDR_IN address = { 0 };
int sizeAddress = sizeof(address);
result = getpeername(clientSockets[i], (SOCKADDR*)&address, &sizeAddress);
ViewConnectedIPPort(address);
}
_tprintf(_T("-----------------------------------------\n"));
}
unsigned int _stdcall ThreadFuncExit(void* lpParameter)
{
char key = -1;
while (1)
{
key = getchar();
if (key == 'q')
{
//EnterCriticalSection(&cs);
BOOL result1 = WaitForSingleObject(hMutex, INFINITE);
_tprintf(_T("모든 클라이언트의 접속을 종료합니다....\n"));
for (int i = 0; i < clientCount; i++)
{
closesocket(clientSockets[i]);
}
clientCount = 0;
TotalClients();
//LeaveCriticalSection(&cs);
result1 = ReleaseMutex(hMutex);
break;
}
}
return 0;
}
728x90
반응형