2009. 6. 1. 13:43 TCP / IP
[ tcp / ip ] - Echo Server
- #include <iostream>
- #include <winsock2.h>
- #pragma comment(lib, "ws2_32.lib")
- using namespace std;
- const int MAX_LEN = 100;
- typedef struct
- {
- SOCKET hClntSock;
- SOCKADDR_IN clntAddr;
- }PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
- typedef struct
- {
- OVERLAPPED overlapped;
- char buffer[MAX_LEN];
- WSABUF wsaBuf;
- }PER_IO_DATA, *LPPER_IO_DATA;
- DWORD WINAPI CompletionThread(LPVOID ComplectionPortIO);
- void ErrorHandling(char * msg);
- int main(void)
- {
- WSADATA wsaData;
- HANDLE hCompletionPort;
- SYSTEM_INFO SystemInfo;
- SOCKADDR_IN servAddr;
- LPPER_IO_DATA PerIoData;
- LPPER_HANDLE_DATA PerHandleData;
- SOCKET hServSock;
- unsigned long RecvBytes;
- unsigned long i, Flags;
- if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
- ErrorHandling("윈속초기화에러");
- //1. Completion Port 생성
- hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,0, 0);
- GetSystemInfo(&SystemInfo);
- //2. 쓰레드를 CPU 개수만큼 생성.
- for (i = 0; i < SystemInfo.dwNumberOfProcessors; i++)
- CreateThread(NULL, 0, CompletionThread, (LPVOID)hCompletionPort, 0, NULL);
- hServSock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
- servAddr.sin_family = AF_INET;
- servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servAddr.sin_port = htons((u_short)atoi("9999"));
- bind(hServSock, (SOCKADDR * )&servAddr, sizeof(servAddr));
- listen(hServSock, 5);
- while (true)
- {
- SOCKET hClntSock;
- SOCKADDR_IN clntAddr;
- int addrLen = sizeof(clntAddr);
- hClntSock = accept(hServSock, (SOCKADDR *)&clntAddr, &addrLen);
- // 연결된 클라이언트의 소켓 핸들 정보와 주소 정보를 설정.
- PerHandleData =
- (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
- PerHandleData->hClntSock = hClntSock;
- memcpy(&(PerHandleData->clntAddr), &clntAddr, addrLen);
-
- //3. Overlapped 소켓과 CompletionPort의 연결.
- CreateIoCompletionPort((HANDLE)hClntSock, hCompletionPort, (DWORD)PerHandleData, 0);
- //클라이언트를 위한 버퍼를 설정, OVERLAPPED 변수 초기화
- PerIoData = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
- memset(&(PerIoData->overlapped), 0, sizeof(OVERLAPPED));
- PerIoData->wsaBuf.len = MAX_LEN;
- PerIoData->wsaBuf.buf = PerIoData->buffer;
- Flags = 0;
- //4. 중첨된 데이터 입력.
- WSARecv(PerHandleData->hClntSock, // 데이터 입력소켓.
&(PerIoData->wsaBuf), //데이터 입력 버퍼 포인터.
1, //데이터 입력버퍼의 수.
&RecvBytes,
&Flags,
&(PerIoData->overlapped), //OVERLAPPED 변수 포인터.
NULL); - }
- return 0;
- }
- DWORD WINAPI CompletionThread(LPVOID pComPort)
- {
- HANDLE hCompletionPort = (HANDLE)pComPort;
- DWORD BytesTransferred;
- LPPER_HANDLE_DATA PerHandleData;
- LPPER_IO_DATA PerIoData;
- DWORD Flags;
- while (true)
- {
- //5. 입. 출력이 완료된 소켓의 정보를 얻음.
- GetQueuedCompletionStatus(hCompletionPort, //Completion Port
&BytesTransferred, //전송된 바이트수.
(LPDWORD)&PerHandleData,
(LPOVERLAPPED *)&PerIoData,
INFINITE); - if (BytesTransferred == 0) // EOF전송시
- {
- closesocket(PerHandleData->hClntSock);
- free(PerHandleData);
- free(PerIoData);
- continue;
- }
- //6. 메시지! 클라이언트로 에코.
- PerIoData->wsaBuf.len = BytesTransferred;
- WSASend(PerHandleData->hClntSock, &(PerIoData->wsaBuf), 1, NULL, 0, NULL, NULL);
- //Receive Again
- memset(&(PerIoData->overlapped), 0, sizeof(OVERLAPPED));
- PerIoData->wsaBuf.len = MAX_LEN;
- PerIoData->wsaBuf.buf = PerIoData->buffer;
- Flags = 0;
-
WSARecv(PerHandleData->hClntSock, &(PerIoData->wsaBuf),
1, NULL, &Flags, &(PerIoData->overlapped), NULL);
- }
- return 0;
- }
- void ErrorHandling(char * msg)
- {
- fputs(msg, stderr);
- fputc('\n', stderr);
- exit(1);
- }