#include #include #include #include #include #pragma comment(lib, "ws2_32.lib") #define IP_ADDRESS 127.0.0.1 #define PORT_ADDRESS 5000 //template //class COverLapped : public OVERLAPPED //{ //public: // COverLapped(void) // { // m_WsaBuf.len = BUFSIZE; // m_WsaBuf.buf = reinterpret_cast(buffer); // } // virtual ~COverLapped(void) {} // //private: //protected: //public: // static const UINT BUFSIZE = 4096; // // typedef enum _E_OP // { // READY = 0x00, // CREATE, // BIND, // LISTEN, // CONNECT, // ACCEPT, // SEND, // RECV, // }E_OP; // // E_OP m_eOperator; // // WSABUF m_WsaBuf; // _Type buffer[BUFSIZE]; //}; static const UINT BUFSIZE = 4096; class COverLapped : public OVERLAPPED { public: COverLapped(void) : m_eOperator(E_OP::READY) { } ~COverLapped(void) {} private: protected: public: typedef enum _E_OP { READY = 0x00, CREATE, BIND, LISTEN, CONNECT, ACCEPT, SEND, RECV, }E_OP; E_OP m_eOperator; WSABUF m_WsaBuf; CHAR m_buffer[BUFSIZE]; }; class CIocpSocket { public: CIocpSocket(void) {} ~CIocpSocket(void) { closesocket(m_Socket); WSACleanup(); } private: CIocpSocket& operator=(const CIocpSocket&) {} SOCKET m_Socket; SOCKADDR_IN m_SocketAddr_in; HANDLE m_IocpHandle; HANDLE *m_ThreadHandle; COverLapped m_SendBuf; COverLapped m_RecvBuf; protected: public: bool CreateIocp(void) { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData)) { int nErrorCode = WSAGetLastError(); return false; } m_IocpHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (!m_IocpHandle) { int nErrorCode = WSAGetLastError(); return false; } m_Socket = WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if (m_Socket == INVALID_SOCKET) { int nErrorCode = WSAGetLastError(); return false; } // PC ¸®¼Ò½º Á¤º¸ SYSTEM_INFO systemInfo; GetSystemInfo(&systemInfo); // CPU Á¤º¸¿¡ µû¸¥ ¾²·¹µå »ý¼º UINT dThreadCount = systemInfo.dwNumberOfProcessors * 2; m_ThreadHandle = new HANDLE[dThreadCount]; for (int i = 0; i < 1; ++i) { m_ThreadHandle[i] = reinterpret_cast(_beginthreadex(NULL, NULL, IOCP_QUEUE_THREAD_PROC, (LPVOID)this, 0, NULL)); } return true; } bool Bind(UINT dPort) { memset(&m_SocketAddr_in, 0, sizeof(SOCKADDR_IN)); m_SocketAddr_in.sin_family = AF_INET; m_SocketAddr_in.sin_addr.s_addr = htonl(INADDR_ANY); m_SocketAddr_in.sin_port = htons(dPort); if (bind(m_Socket, (SOCKADDR *)&m_SocketAddr_in, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) { int nErrorCode = WSAGetLastError(); return false; } return true; } bool Listen(UINT dBacklog = SOMAXCONN) { if (listen(m_Socket, dBacklog) == SOCKET_ERROR) { int nErrorCode = WSAGetLastError(); return false; } return true; } bool Connect(LPTSTR pszIpAddress, WORD wPort) { m_SocketAddr_in.sin_family = AF_INET; int nAddrLen = sizeof(SOCKADDR_IN); WSAStringToAddress(pszIpAddress, AF_INET, NULL, (SOCKADDR*)&m_SocketAddr_in, &nAddrLen); m_SocketAddr_in.sin_port = htons(wPort); //if (WSAConnect(m_Socket, (struct sockaddr*)&m_SocketAddr_in, sizeof(SOCKADDR_IN), NULL, NULL, NULL, NULL) < 0) if (connect(m_Socket, (struct sockaddr*)&m_SocketAddr_in, sizeof(SOCKADDR_IN)) < 0) { int err = WSAGetLastError(); return false; } return true; } CIocpSocket* Accept(void) { int nAddrLen = sizeof(SOCKADDR_IN); CIocpSocket *pIocpClient = new CIocpSocket(); pIocpClient->m_Socket = accept(m_Socket, (SOCKADDR*)&pIocpClient->m_SocketAddr_in, &nAddrLen); if (pIocpClient->m_Socket == INVALID_SOCKET) { delete pIocpClient; int err = WSAGetLastError(); return NULL; } memcpy(&(pIocpClient->m_SocketAddr_in), &pIocpClient->m_SocketAddr_in, nAddrLen); if (!CreateIoCompletionPort((HANDLE)pIocpClient->m_Socket, m_IocpHandle, (DWORD)pIocpClient, 0)) { delete pIocpClient; int nErrorCode = WSAGetLastError(); return false; } return pIocpClient; } static UINT __stdcall IOCP_QUEUE_THREAD_PROC(LPVOID lpvoid) { CIocpSocket* pCIocpSocket = static_cast(lpvoid); while (TRUE) { DWORD dwNumberOfBytesTransferred = 0; CIocpSocket *pCIocpSocket_Target = NULL; COverLapped *pOverlapped = NULL; //PER_IO_DATA *pPER_IO_DATA = NULL; BOOL bResult = GetQueuedCompletionStatus(pCIocpSocket->m_IocpHandle, &dwNumberOfBytesTransferred, (LPDWORD)&pCIocpSocket_Target, //(LPOVERLAPPED*)&pPER_IO_DATA, (LPOVERLAPPED*)&pOverlapped, INFINITE); if (bResult == FALSE || dwNumberOfBytesTransferred == 0) { closesocket(pCIocpSocket_Target->m_Socket); pCIocpSocket_Target->OnDisconnect(); continue; } //switch (pPER_IO_DATA->rwMode) switch (pOverlapped->m_eOperator) { case COverLapped::E_OP::SEND: pCIocpSocket_Target->OnSend(pOverlapped->m_WsaBuf.buf, dwNumberOfBytesTransferred); break; case COverLapped::E_OP::RECV: pCIocpSocket_Target->OnRecv(pOverlapped->m_WsaBuf.buf, dwNumberOfBytesTransferred); pCIocpSocket_Target->send((BYTE*)pOverlapped->m_WsaBuf.buf, dwNumberOfBytesTransferred); break; } } return 0; } void send(BYTE *pData, UINT dDataLength) { UINT dLessSendCount = dDataLength; while ((int)dDataLength >= 1) { memset((OVERLAPPED*)&m_SendBuf, 0, sizeof(OVERLAPPED)); m_SendBuf.m_eOperator = COverLapped::E_OP::SEND; m_SendBuf.m_WsaBuf.len = dDataLengthm_eOperator = COverLapped::E_OP::RECV; pOverlapped->m_WsaBuf.len = BUFSIZE; pOverlapped->m_WsaBuf.buf = pOverlapped->m_buffer; //PER_IO_DATA *pPER_IO_DATA = new PER_IO_DATA(); //memset(&(pPER_IO_DATA->overlapped), 0, sizeof(OVERLAPPED)); //pPER_IO_DATA->rwMode = 2; //pPER_IO_DATA->wsaBuf.len = BUFSIZE; //pPER_IO_DATA->wsaBuf.buf = pPER_IO_DATA->buffer; DWORD dwFlags = 0; WSARecv(m_Socket, &(pOverlapped->m_WsaBuf), 1/*pOverlapped->BUFSIZE*/, NULL, &dwFlags, (OVERLAPPED*)pOverlapped, NULL); //WSARecv(m_Socket, &(pPER_IO_DATA->wsaBuf), 1/*pOverlapped->BUFSIZE*/, NULL, &dwFlags, &(pPER_IO_DATA->overlapped), NULL); } //virtual void OnAccept(void); //virtual void OnConnect(void); virtual void OnRecv(CHAR *pData, UINT dDataLength) { printf("CIocpSocket OnRecv(Port : %d) : %s\r\n", m_SocketAddr_in.sin_port, pData); } virtual void OnSend(CHAR *pData, UINT dDataLength) { printf("CIocpSocket OnSend(Port : %d) : %s\r\n", m_SocketAddr_in.sin_port, pData); } virtual void OnDisconnect(void) { printf("CIocpSocket OnDisconnect\r\n"); } }; class CIocpServer : public CIocpSocket { public: private: protected: public: void run(void) { CreateIocp(); Bind(5000); Listen(); while (TRUE) { CIocpSocket *pClientSocket = Accept(); pClientSocket->recv(); } } virtual void OnRecv(BYTE *pData, UINT dDataLength) { printf("CIocpServer OnRecv : %s\r\n", pData); } }; int main(int argc, char *argv[]) { CIocpServer is; is.run(); return 0; }