대충 IOCP
2018. 7. 17. 13:29
APC : Asynchronous Procedure Call 실험
2018. 7. 12. 12:46
비동기 프로시저 호출을 하기 위해서는 경보가능 대기 상태를 알려줄수 있는 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, 0, sizeof(_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, NULL, 0, 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, 1, NULL, &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, 1, NULL, &dwFlags, pSI, RecvCallback); } } | cs |
'서버프로그래밍' 카테고리의 다른 글
PostThreadMessage의 ThreadId (0) | 2018.08.27 |
---|---|
ZeroByteRecv - PageLocking 관련 (0) | 2018.08.22 |
서버실험용 간단 클라이언트 (0) | 2018.07.12 |
WSABUF 에 대한 실험 (0) | 2018.06.27 |
서버나 클라에 send시 구조체 보내기 (0) | 2018.06.27 |
서버실험용 간단 클라이언트
2018. 7. 12. 11:25
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, 0, NULL); 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, 1000, 0); 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(NULL, 0, RecvData, (LPVOID)sock, 0, NULL); WSABUF wsaBuf; memset(&wsaBuf, 0, sizeof(WSABUF)); char buf[200]; while (true) { memset(buf, '\0', 200); cout << "Chat : "; cin >> buf; send(sock, buf, sizeof(buf), 0); } return 0; } | cs |
'서버프로그래밍' 카테고리의 다른 글
ZeroByteRecv - PageLocking 관련 (0) | 2018.08.22 |
---|---|
APC : Asynchronous Procedure Call 실험 (0) | 2018.07.12 |
WSABUF 에 대한 실험 (0) | 2018.06.27 |
서버나 클라에 send시 구조체 보내기 (0) | 2018.06.27 |
UDP를 이용한 채팅서버 만들기 (0) | 2018.06.24 |