서버
/*
## 소켓 서버 : 1 v n - asynchronous Server - eventSelect
1. socket() : 소켓생성
2. bind() : 소켓설정
3. listen() : 수신대기열생성
4. accept() : 연결대기
5. read()&write()
WIN recv()&send : 데이터 읽고쓰기
6. close()
WIN closesocket : 소켓종료
*/
#include "stdafx.h"
#include <winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define MAX_BUFFER 1024
#define SERVER_PORT 3500
struct SOCKETINFO
{
SOCKET socket;
char messageBuffer[MAX_BUFFER];
int receiveBytes;
int sendBytes;
};
int _tmain(int argc, _TCHAR* argv[])
{
// 1. 소켓생성 > 2. 소켓설정 > 3. 수신대기열생성
// Winsock Start - windock.dll 로드
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
{
printf("Error - Can not load 'winsock.dll' file\n");
return 1;
}
// 1. 소켓생성
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSocket == INVALID_SOCKET)
{
printf("Error - Invalid socket\n");
return 1;
}
// 서버정보 객체설정
SOCKADDR_IN serverAddr;
memset(&serverAddr, 0, sizeof(SOCKADDR_IN));
serverAddr.sin_family = PF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
// 2. 소켓설정
if (bind(listenSocket, (struct sockaddr*)&serverAddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
printf("Error - Fail bind\n");
// 6. 소켓종료
closesocket(listenSocket);
// Winsock End
WSACleanup();
return 1;
}
// 3. 수신대기열생성
if (listen(listenSocket, 5) == SOCKET_ERROR)
{
printf("Error - Fail listen\n");
// 6. 소켓종료
closesocket(listenSocket);
// Winsock End
WSACleanup();
return 1;
}
// Create Event - 최대 갯수의 소켓과 이벤트 객체 생성
struct SOCKETINFO *sockets[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS];
int totalIndex = 0;
// - Listen Socket 설정
struct SOCKETINFO *socketInfo;
socketInfo = (struct SOCKETINFO *)malloc(sizeof(struct SOCKETINFO));
memset((struct SOCKETINFO *)socketInfo, 0x00, sizeof(struct SOCKETINFO));
socketInfo->socket = listenSocket;
socketInfo->receiveBytes = 0;
socketInfo->sendBytes = 0;
sockets[totalIndex] = socketInfo;
// - 이벤트 객체 생성
events[totalIndex] = WSACreateEvent();
if (events[totalIndex] == WSA_INVALID_EVENT)
{
printf("Error - Event Create Failure\n");
return 1;
}
// - 이벤트 객체를 소켓과 묶음
if (WSAEventSelect(listenSocket, events[totalIndex], FD_ACCEPT | FD_CLOSE) == SOCKET_ERROR)
{
printf("Error - Event Select Failure\n");
return 1;
}
totalIndex = totalIndex + 1;
WSANETWORKEVENTS networkEvents;
SOCKADDR_IN clientAddr;
int addrLen = sizeof(SOCKADDR_IN);
memset(&clientAddr, 0, addrLen);
SOCKET clientSocket;
char messageBuffer[MAX_BUFFER];
while (1)
{
// 이벤트를 기다림
int eventIndex = WSAWaitForMultipleEvents(totalIndex, events, FALSE, WSA_INFINITE, FALSE);
// - 예외처리
if (eventIndex == WSA_WAIT_FAILED)
{
printf("Error - Event Wait Failure\n");
break;
}
// - 신호상태인 이벤트객체의 정보를 가져옴
if (WSAEnumNetworkEvents(
sockets[eventIndex - WSA_WAIT_EVENT_0]->socket,
events[eventIndex - WSA_WAIT_EVENT_0], &networkEvents) == SOCKET_ERROR)
{
printf("Error - Event Type Error\n");
break;
}
// >> FD_ACCEPT : 클라이언트 요청이벤트일 경우 accept함수로 소켓을 만들고 이벤트객체와 묶음
if (networkEvents.lNetworkEvents& FD_ACCEPT)
{
if (networkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
{
printf("Error - Network Error\n");
break;
}
if (totalIndex > WSA_MAXIMUM_WAIT_EVENTS)
{
printf("Error - Connection Full\n");
break;
}
// 4. 연결대기
clientSocket = accept(sockets[eventIndex - WSA_WAIT_EVENT_0]->socket, (struct sockaddr *)&clientAddr, &addrLen);
if (clientSocket == INVALID_SOCKET)
{
printf("Error - Fail accept\n");
continue;
}
// - 소켓생성
sockets[totalIndex] = (struct SOCKETINFO *)malloc(sizeof(struct SOCKETINFO));
memset((struct SOCKETINFO *)sockets[totalIndex], 0x00, sizeof(struct SOCKETINFO));
sockets[totalIndex]->socket = clientSocket;
sockets[totalIndex]->receiveBytes = 0;
sockets[totalIndex]->sendBytes = 0;
// - 이벤트 객체 생성
events[totalIndex] = WSACreateEvent();
if (events[totalIndex] == WSA_INVALID_EVENT)
{
printf("Error - Event Create Failure\n");
return 1;
}
// - 이벤트 객체를 소켓과 묶음
if (WSAEventSelect(clientSocket, events[totalIndex], FD_READ) == SOCKET_ERROR)
{
printf("Error - Event Select Failure\n");
return 1;
}
totalIndex = totalIndex + 1;
}
// >> FD_READ : 읽기 이벤트일 경우
if (networkEvents.lNetworkEvents& FD_READ)
{
// 5-1. 데이터 읽기
int receiveBytes = recv(sockets[eventIndex - WSA_WAIT_EVENT_0]->socket, messageBuffer, MAX_BUFFER, 0);
if (receiveBytes > 0)
{
printf("TRACE - Receive message : %s (%d bytes)\n", messageBuffer, receiveBytes);
// 5-2. 데이터 쓰기
int sendBytes = send(sockets[eventIndex - WSA_WAIT_EVENT_0]->socket, messageBuffer, strlen(messageBuffer), 0);
if (sendBytes > 0)
{
printf("TRACE - Send message : %s (%d bytes)\n", messageBuffer, sendBytes);
}
}
}
// >> FD_CLOSE : 종료 이벤트일 경우
if (networkEvents.lNetworkEvents& FD_CLOSE)
{
// 6-1. 클라이언트 소켓종료
closesocket(sockets[eventIndex - WSA_WAIT_EVENT_0]->socket);
// 메모리 해제
free((void *)sockets[eventIndex - WSA_WAIT_EVENT_0]);
// 이벤트 객체 닫기
if (WSACloseEvent(events[eventIndex]) == TRUE)
{
printf("Error - Event Close Success\n");
}
else
{
printf("Error - Event Close Failure\n");
}
for (int i = eventIndex; i < totalIndex; i++)
{
sockets[i] = sockets[i + 1];
events[i] = events[i + 1];
}
totalIndex--;
}
}
// 6-2. 리슨 소켓종료
closesocket(listenSocket);
// Winsock End
WSACleanup();
return 0;
}
클라이언트
/*
## 소켓 서버 : 1 v n - asynchronous Server - eventSelect
1. socket() : 소켓생성
2. connect() : 연결요청
3. read()&write()
WIN recv()&send : 데이터 읽고쓰기
4. close()
WIN closesocket : 소켓종료
*/
#include "stdafx.h"
#include <winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define MAX_BUFFER 1024
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 3500
int _tmain(int argc, _TCHAR* argv[])
{
// Winsock Start - winsock.dll 로드
WSADATA WSAData;
if (WSAStartup(MAKEWORD(2, 0), &WSAData) != 0)
{
printf("Error - Can not load 'winsock.dll' file\n");
return 1;
}
// 1. 소켓생성
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSocket == INVALID_SOCKET)
{
printf("Error - Invalid socket\n");
return 1;
}
// 서버정보 객체설정
SOCKADDR_IN serverAddr;
memset(&serverAddr, 0, sizeof(SOCKADDR_IN));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
serverAddr.sin_addr.S_un.S_addr = inet_addr(SERVER_IP);
// 2. 연결요청
if (connect(listenSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
printf("Error - Fail to connect\n");
// 4. 소켓종료
closesocket(listenSocket);
// Winsock End
WSACleanup();
return 1;
}
else
{
printf("Server Connected\n* Enter Message\n->");
}
while (1)
{
// 메시지 입력
char messageBuffer[MAX_BUFFER];
int i, bufferLen;
for (i = 0; 1; i++)
{
messageBuffer[i] = getchar();
if (messageBuffer[i] == '\n')
{
messageBuffer[i++] = '\0';
break;
}
}
bufferLen = i;
// 3-1. 데이터 쓰기
int sendBytes = send(listenSocket, messageBuffer, bufferLen, 0);
if (sendBytes > 0)
{
printf("TRACE - Send message : %s (%d bytes)\n", messageBuffer, sendBytes);
// 3-2. 데이터 읽기
int receiveBytes = recv(listenSocket, messageBuffer, MAX_BUFFER, 0);
if (receiveBytes > 0)
{
printf("TRACE - Receive message : %s (%d bytes)\n* Enter Message\n->", messageBuffer, receiveBytes);
}
}
}
// 4. 소켓종료
closesocket(listenSocket);
// Winsock End
WSACleanup();
return 0;
}