SockStart.zip


IOCP 대충 만들어놓기!

비동기 프로시저 호출을 하기 위해서는 경보가능 대기 상태를 알려줄수 있는 EX 확장 함수가 필요하다.

WaitFor~Ex , 


+


이벤트나 작업개시를 알리는 동시와 함께 그 작업을 처리할 콜백 함수포인터를 넣어주는 WSARecv ,, ReadEx 등 이 필요하다.


각각의 스레드는 자신만의 고유한 APC 큐를 가진다.


WaitFor ~ Ex 같은 함수들의 반환 값은 WAIT_FALI, WAIT_OBEJCT, WAIT_TIMEOUT, WAIT_ABANDONED 등 이있고


경보가능 대기 상태에서 WAIT_IO_COMPLETION 이 리턴 된다면 콜백함수의 실행이 완료 되었기 떄문에 스레드가 깨어났었다는 것을 알린다.

(즉 콜백함수를 실행하고 다시 되돌아 온것)


QueueUserAPC 는 사용자가 직접 정의한 콜백 함수를 특정 스레드의 APC 큐에 추가하는데 사용됨


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
 
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <set>
#include <WinSock2.h>
 
 
#pragma comment(lib,"ws2_32.LIB")
 
using namespace std;
 
struct SOCK_ITEM;
typedef std::set<SOCK_ITEM*> SOCK_SET;
 
void CALLBACK RecvCallback(DWORD dwErrCode, DWORD dwTranBytes, LPOVERLAPPED pOL, DWORD dwFlags);
 
struct SOCK_ITEM :OVERLAPPED {
    SOCKET _sock;
    char _buff[512];
    SOCK_SET* _pSet;
 
    SOCK_ITEM(SOCKET sock, SOCK_SET* pSet) {
        hEvent = NULL;
        Offset = OffsetHigh = 0;
        memset(_buff, 0sizeof(_buff));
 
        _sock = sock;
        _pSet = pSet;
    }
};
 
typedef SOCK_ITEM* PSOCK_ITEM;
 
HANDLE g_hevExit;
 
int main() {
    g_hevExit = CreateEvent(NULL, TRUE, FALSE, NULL);
    
    WSADATA wsaData;
    BYTE nMajor, nMinor;
    WORD wVersionRequested;
    nMinor = 2, nMajor = 2;
    wVersionRequested = MAKEWORD(nMinor, nMajor);
    if (WSAStartup(wVersionRequested, &wsaData) == SOCKET_ERROR)
        cout << "Sock Start Failed\n";
 
    if (LOBYTE(wsaData.wVersion) != nMinor || HIBYTE(wsaData.wVersion) != nMajor) {
        cout << "Sock Version nat matched" << endl;
        WSACleanup();
    }
    SOCKET LstnSock;
    sockaddr_in tcpAddr;
    LstnSock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL0, WSA_FLAG_OVERLAPPED);
    if (LstnSock == INVALID_SOCKET){}
    BOOL On = true;;
    //    setsockopt(LstnSock, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char*)&On, sizeof(On));
    // 백로그 큐의 활성화를 막아서 포트스캔을 피함.
 
    tcpAddr.sin_family = PF_INET;
    tcpAddr.sin_port = htons(9000);
    tcpAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(LstnSock, (struct sockaddr*)&tcpAddr, sizeof(tcpAddr)) == SOCKET_ERROR) {
        cout << "bind error ";
    }
 
    if (listen(LstnSock, SOMAXCONN) == SOCKET_ERROR) {
        cout << "Listen error" << endl;
    }
 
    WSAEVENT hEvent = WSACreateEvent();
    WSAEventSelect(LstnSock, hEvent, FD_ACCEPT);
 
    SOCK_SET siols;
    HANDLE arStnObjs[2= { g_hevExit,hEvent };
    while (true) {
        DWORD dwWaitRet = WaitForMultipleObjectsEx(2, arStnObjs, FALSE, INFINITE, TRUE);
 
        if (dwWaitRet == WAIT_OBJECT_0) {
            cout << "exit while " << endl;
        }
        if (dwWaitRet == WAIT_IO_COMPLETION) {
            cout << "Complelition Roution Execute " << endl;
 
        /*    while (true) {
            }*/
        }
 
        WSANETWORKEVENTS ne;
        WSAEnumNetworkEvents(LstnSock, hEvent, &ne);
        if (ne.lNetworkEvents & FD_ACCEPT) {
            sockaddr_in cliaddr;
            int addrlen = sizeof(cliaddr);
            SOCKET socket = accept(LstnSock, (sockaddr*)&cliaddr, &addrlen);
            if (socket == INVALID_SOCKET) {
                cout << "accept Failed " << WSAGetLastError() << endl;
            }
            cout << "New Client " << inet_ntoa(cliaddr.sin_addr) << " Connection " << endl;
 
            PSOCK_ITEM pSI = new SOCK_ITEM(socket, &siols);
 
            WSABUF wb;
            wb.buf = pSI->_buff;
            wb.len = sizeof(pSI->_buff);
            DWORD dwFlags = 0;
            int nSockRet = WSARecv(socket, &wb, 1NULL&dwFlags, pSI, RecvCallback);
 
            if (nSockRet == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
                cout << " failed " << endl;
                 
                cout << "WSAGetLastError() :" << WSAGetLastError() << endl;
                closesocket(socket);
                delete pSI;
            }
            else
                siols.insert(pSI);
        }
    }
    return 0;
}
 
void CALLBACK RecvCallback(DWORD dwErrCode, DWORD dwTranBytes, LPOVERLAPPED pOL, DWORD dwFlags) {
    PSOCK_ITEM pSI = (PSOCK_ITEM)pOL;
    if (dwTranBytes > 0 && dwErrCode == 0) {
        pSI->_buff[dwTranBytes] = 0;
        cout << pSI->_buff << endl;
 
        WSABUF wb;
        wb.buf = pSI->_buff, wb.len = sizeof(pSI->_buff);
        WSARecv(pSI->_sock, &wb, 1NULL&dwFlags, pSI, RecvCallback);
    
 
    
    }
}
cs


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
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <WinSock2.h>
using namespace std;
 
#pragma comment(lib,"ws2_32.LIB")
 
struct temp {
    int age;
    char buf[10];
};
 
void Exception(const char* msg) {
    cout << msg << endl;
    LPVOID lpOSMsg;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, WSAGetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPSTR)&lpOSMsg, 0NULL);
    cout << "[" << (char*)lpOSMsg << "]" << endl;
    LocalFree(lpOSMsg);
}
 
DWORD WINAPI RecvData(LPVOID pParam) {
    SOCKET sock = (SOCKET)pParam;
    char buf[1000]; 
 
    //ULONG isNonBlocking = 1;
    //ioctlsocket(sock,        //Non-Blocking으로 변경할 소켓
    //    FIONBIO,       //변경할 소켓의 입출력 모드
    //    &isNonBlocking //넘기는 인자, 여기서는 nonblocking설정 값
    //);
 
    while (true) {
        memset(buf, '\0'1000);
        
        int len = recv(sock, buf, 10000);
        if (WSAGetLastError() == WSAEWOULDBLOCK) {
        //    Sleep(2000);
        }
 
        if (len > 0) {
            cout << buf << endl;
        }
 
    }
 
}
 
int main() {
    WSADATA wsaData;
 
    BYTE nMajor = 2, nMinor = 2;
 
    WORD wVersionRequested = MAKEWORD(nMinor, nMajor);
    
    if (WSAStartup(wVersionRequested, &wsaData) == SOCKET_ERROR) {
        cout << "socket Initialize failed " << endl;
        return -1;
    }
    if (LOBYTE(wsaData.wVersion) != nMajor || HIBYTE(wsaData.wVersion) != nMinor) {
        cout << "socket version not equal" << endl;
        WSACleanup();
        return -1;
    }
 
    char ServerIP[50= { '\0' };
    SOCKET sock =  socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if (sock == INVALID_SOCKET)
        Exception("Do not make Socket");
 
    cin >> ServerIP;
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9000);
    addr.sin_addr.s_addr = inet_addr(ServerIP);
 
    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
        Exception("Socket Error");
    
    HANDLE hThread = CreateThread(NULL0, RecvData, (LPVOID)sock, 0NULL);
 
 
    WSABUF wsaBuf;
    memset(&wsaBuf, 0sizeof(WSABUF));
    char buf[200];
 
    
    while (true) {
        memset(buf, '\0'200);
        cout << "Chat : ";
    
        cin >> buf;
 
        send(sock, buf, sizeof(buf), 0);
    
}
    return 0;
}
cs


+ Recent posts