초간단 IOCP 예제를 소개한다!(서버/클라이언트)
잘 동작하는 소스이므로 참고 자료로 사용하면 좋을 것 같다!(그대로 복사해서 빌드를 하면 된다!)
1. IOCP 서버
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 |
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <process.h>
#define BUFSIZE 1024
typedef struct
{
SOCKET hClntSock;
SOCKADDR_IN clntAddr;
} PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
typedef struct
{
OVERLAPPED overlapped;
char buffer[BUFSIZE];
WSABUF wsaBuf;
} PER_IO_DATA, *LPPER_IO_DATA;
unsigned int __stdcall CompletionThread(LPVOID pComPort);
void ErrorHandling(char *message);
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char** argv)
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
for(int i=0; i<SystemInfo.dwNumberOfProcessors; ++i)
_beginthreadex(NULL, 0, CompletionThread, (LPVOID)hCompletionPort, 0, NULL);
SOCKET hServSock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
SOCKADDR_IN servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//servAddr.sin_port = htons(atoi("2738"));
servAddr.sin_port = htons(2738);
bind(hServSock, (SOCKADDR*)&servAddr, sizeof(servAddr));
listen(hServSock, 5);
LPPER_IO_DATA PerIoData;
LPPER_HANDLE_DATA PerHandleData;
int RecvBytes;
int i, Flags;
while(TRUE)
{
SOCKADDR_IN clntAddr;
int addrLen = sizeof(clntAddr);
SOCKET hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &addrLen);
PerHandleData = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
PerHandleData->hClntSock = hClntSock;
memcpy(&(PerHandleData->clntAddr), &clntAddr, addrLen);
CreateIoCompletionPort((HANDLE)hClntSock, hCompletionPort, (DWORD)PerHandleData, 0);
PerIoData = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
memset(&(PerIoData->overlapped), 0, sizeof(OVERLAPPED));
PerIoData->wsaBuf.len = BUFSIZE;
PerIoData->wsaBuf.buf = PerIoData->buffer;
Flags = 0;
WSARecv(PerHandleData->hClntSock, &(PerIoData->wsaBuf), 1, (LPDWORD)&RecvBytes, (LPDWORD)&Flags, &(PerIoData->overlapped), NULL);
}
return 0;
}
unsigned int __stdcall CompletionThread(LPVOID pComPort)
{
HANDLE hCompletionPort = (HANDLE)pComPort;
DWORD BytesTransferred;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_DATA PerIoData;
DWORD flags;
while(1) {
GetQueuedCompletionStatus(hCompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED*)&PerIoData, INFINITE);
if(BytesTransferred == 0)
{
closesocket(PerHandleData->hClntSock);
free(PerHandleData);
free(PerIoData);
continue;
}
PerIoData->wsaBuf.buf[BytesTransferred] = '\0';
printf("Recv[%s]\n", PerIoData->wsaBuf.buf);
PerIoData->wsaBuf.len = BytesTransferred;
WSASend(PerHandleData->hClntSock, &(PerIoData->wsaBuf), 1, NULL, 0, NULL, NULL);
memset(&(PerIoData->overlapped), 0, sizeof(OVERLAPPED));
PerIoData->wsaBuf.len = BUFSIZE;
PerIoData->wsaBuf.buf = PerIoData->buffer;
flags = 0;
WSARecv(PerHandleData->hClntSock, &(PerIoData->wsaBuf), 1, NULL, &flags, &(PerIoData->overlapped), NULL);
}
return 0;
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
} |
cs |
2. IOCP 클라이언트
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 |
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
void ErrorHandling(char *message);
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
SOCKET hSocket = WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if(hSocket == INVALID_SOCKET)
ErrorHandling("socket() error");
SOCKADDR_IN recvAddr;
memset(&recvAddr, 0, sizeof(recvAddr));
recvAddr.sin_family = AF_INET;
recvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
recvAddr.sin_port = htons(2738);
if(connect(hSocket, (SOCKADDR*)&recvAddr, sizeof(recvAddr)) == SOCKET_ERROR)
ErrorHandling("connect() error!");
WSAEVENT event = WSACreateEvent();
WSAOVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = event;
WSABUF dataBuf;
char message[1024] = {0,};
int sendBytes = 0;
int recvBytes = 0;
int flags = 0;
while(true)
{
flags = 0;
printf("전송할데이터(종료를원할시exit)\n");
scanf("%s", message);
if(!strcmp(message, "exit")) break;
dataBuf.len = strlen(message);
dataBuf.buf = message;
if(WSASend(hSocket, &dataBuf, 1, (LPDWORD)&sendBytes, 0, &overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
ErrorHandling("WSASend() error");
}
WSAWaitForMultipleEvents(1, &event, TRUE, WSA_INFINITE, FALSE);
WSAGetOverlappedResult(hSocket, &overlapped, (LPDWORD)&sendBytes, FALSE, NULL);
printf("전송된바이트수: %d \n", sendBytes);
if(WSARecv(hSocket, &dataBuf, 1, (LPDWORD)&recvBytes, (LPDWORD)&flags, &overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
ErrorHandling("WSASend() error");
}
printf("Recv[%s]\n",dataBuf.buf);
}
closesocket(hSocket);
WSACleanup();
return 0;
}
void ErrorHandling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
} |
cs |
출처 : http://cafe.naver.com/boolnim/403
'IT노트(구) > C/C++' 카테고리의 다른 글
(C++) char 배열을 int로 변환하는 방법(stringstream 이용) (0) | 2016.01.10 |
---|---|
(C++) cout 표준 출력 방향을 콘솔에서 파일로 전환하는 방법 (0) | 2016.01.07 |
(C언어) float를 char*로 형변환 방법 (0) | 2016.01.05 |
(C언어) winsock을 이용한 http request 예제 (0) | 2016.01.05 |
std::string을 char array로 변환하는 방법 (0) | 2016.01.04 |