반응형
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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | // IOCP_practice.cpp: 콘솔 응용 프로그램의 진입점을 정의합니다. // IOCP => Input/Output Completion Port #include "stdafx.h" #include <WinSock2.h> #include <iostream> #pragma comment(lib, "Ws2_32.lib") #define SERVER_PORT 3500 #define MAX_BUFFER 1024 using namespace std; struct SOCKETINFO { WSAOVERLAPPED overlapped; WSABUF dataBuffer; SOCKET socket; char messageBuffer[MAX_BUFFER]; int receiveBytes; int sendBytes; }; DWORD WINAPI makeThread(LPVOID hIOCP); int main() { // 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 = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); 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"); closesocket(listenSocket); WSACleanup(); return 1; } //3. 수신대기열생성 if (listen(listenSocket, 5) == SOCKET_ERROR) { printf("Error - Fail listen\n"); closesocket(listenSocket); WSACleanup(); return 1; } //완료 결과를 처리하는 객체 생성(IOCP) HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); /*디바이스와 연결할 때는 다음과 같이 사용 HANDLE IOCP = CreateIoCompletionPort(socket, hIOCP, (ULONG_PTR)session, 0); */ // 워커스레드 생성 // -cpu * 2개 SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); int threadCount = systemInfo.dwNumberOfProcessors * 2; unsigned long threadId; // 쓰레드 핸들러 선언 HANDLE *hThread = (HANDLE *)malloc(threadCount * sizeof(HANDLE)); // cpu 갯수 만큼 쓰레드 생성 for (int i = 0; i < threadCount; i++) { hThread[i] = CreateThread(NULL, 0, makeThread, &hIOCP, 0, &threadId); } SOCKADDR_IN clientAddr; int addrLen = sizeof(SOCKADDR_IN); memset(&clientAddr, 0, addrLen); SOCKET clientSocket; SOCKETINFO *socketInfo; DWORD receiveBytes; DWORD flags; while (1) { clientSocket = accept(listenSocket, (struct sockaddr *)&clientAddr, &addrLen); if (clientSocket == INVALID_SOCKET) { printf("Error - Accept Failure\n"); return 1; } socketInfo = (struct SOCKETINFO *)malloc(sizeof(struct SOCKETINFO)); memset((void*)socketInfo, 0x00, sizeof(struct SOCKETINFO)); socketInfo->socket = clientSocket; socketInfo->receiveBytes = 0; socketInfo->sendBytes = 0; socketInfo->dataBuffer.len = MAX_BUFFER; socketInfo->dataBuffer.buf = socketInfo->messageBuffer; flags = 0; hIOCP = CreateIoCompletionPort((HANDLE)clientSocket, hIOCP, (DWORD)socketInfo, 0); if (WSARecv(socketInfo->socket, &socketInfo->dataBuffer, 1, &receiveBytes, &flags, &(socketInfo->overlapped), NULL)) { if (WSAGetLastError() != WSA_IO_PENDING) { printf("Error - IO pending Failure\n"); return 1; } } } closesocket(listenSocket); WSACleanup(); return 0; } DWORD WINAPI makeThread(LPVOID hIOCP) { HANDLE threadHandler = *((HANDLE *)hIOCP); DWORD receiveBytes; DWORD sendBytes; DWORD completionKey; DWORD flags; struct SOCKETINFO *eventSocket; while (1) { // 입출력 완료 대기 if (GetQueuedCompletionStatus(threadHandler, &receiveBytes, &completionKey, (LPOVERLAPPED *)&eventSocket, INFINITE) == 0) { printf("Error - GetQueuedCompletionStatus Failure\n"); closesocket(eventSocket->socket); free(eventSocket); return 1; } eventSocket->dataBuffer.len = receiveBytes; if (receiveBytes == 0) { closesocket(eventSocket->socket); free(eventSocket); continue; } else { printf("TRACE - Receive message : %s (%d bytes)\n", eventSocket->dataBuffer.buf, eventSocket->dataBuffer.len); if (WSASend(eventSocket->socket, &(eventSocket->dataBuffer), 1, &sendBytes, 0, NULL, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSA_IO_PENDING) { printf("Error - Fail WSASend(error_code : %d)\n", WSAGetLastError()); } } printf("TRACE - Send message : %s (%d bytes)\n", eventSocket->dataBuffer.buf, eventSocket->dataBuffer.len); memset(eventSocket->messageBuffer, 0x00, MAX_BUFFER); eventSocket->receiveBytes = 0; eventSocket->sendBytes = 0; eventSocket->dataBuffer.len = MAX_BUFFER; eventSocket->dataBuffer.buf = eventSocket->messageBuffer; flags = 0; if (WSARecv(eventSocket->socket, &(eventSocket->dataBuffer), 1, &receiveBytes, &flags, &eventSocket->overlapped, NULL) == SOCKET_ERROR) { if (WSAGetLastError() != WSA_IO_PENDING) { printf("Error - Fail WSARecv(error_code : %d)\n", WSAGetLastError()); } } } } } |
[코드 출저]: http://myblog.opendocs.co.kr/archives/1206
네트워크 데이터형식 변환 함수
Convert multi-byte integer types from host byte order to network byte order
htons() : Host to network short
htonl() : Host to network long
ntohs() : network to host short
ntohl() : network to host long
서버의 생성 과정
socket() -> bind() -> listen() -> accept() -> read() & write() -> close()
클라이언트 생성 과정
socket() -> connect() -> read() & write() -> close()
반응형
'TIL > 개인공부' 카테고리의 다른 글
[2018 데이터챌린지] 악성코드 탐지 후기 1편 (0) | 2018.11.11 |
---|---|
[IOCP] 클라이언트 코딩 (0) | 2018.09.17 |
공부2 (0) | 2018.09.14 |
[Tensorflow]우분투에 Tensorflow-gpu 버전 설치하기. 2 (0) | 2018.03.19 |
[Tensorflow]우분투에 Tensorflow-gpu 버전 설치하기. 1 (0) | 2018.03.19 |