#ifndef _COMMON_DEFINE_H #define _COMMON_DEFINE_H #include <iostream> #include <map> using namespace std; // // Type of callbacks definition typedef void (*ON_RECEIVE_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); typedef void (*ON_RECEIVE_ERROR_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, int nError); typedef void (*ON_SEND_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); typedef void (*ON_SEND_ERROR_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, int nError); typedef void (*ON_CLOSE_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_CONNECT_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr); // #define BUFFER_SIZE 4096 #define EXIT_FALG 0xFFFFFFFF // typedef struct _tagClientInfo { SOCKET sock; SOCKADDR_IN addrClient; } CLIENT_INFO; typedef struct _tagPerIoData { WSAOVERLAPPED overlapped; WSABUF buffer; char szBuf[BUFFER_SIZE]; int nBufLength; int nOperationType; DWORD dwNumberOfBytes; DWORD dwFlag; DWORD dwBytes; SOCKET sock; SOCKADDR_IN addrClient; } PER_IO_DATA; typedef enum { RECV_POSTED, SEND_POSTED, ACCEPT_POSTED } OPERATION_TYPE; // typedef struct tagServerContext { SOCKET svrSock; SOCKADDR_IN svrSockAddr; BOOL bStart; HANDLE hComplitionPort; void* pVoid; ON_RECEIVE_CALLBACK onReceive; ON_SEND_CALLBACK onSend; ON_CLOSE_CALLBACK onClose; ON_CONNECT_CALLBACK onConnect; ON_RECEIVE_ERROR_CALLBACK onReceiveError; ON_SEND_ERROR_CALLBACK onSendError; tagServerContext() { svrSock = INVALID_SOCKET; memset(&svrSockAddr, 0, sizeof(svrSockAddr)); bStart = FALSE; pVoid = NULL; onReceive = NULL; onSend = NULL; onClose = NULL; onConnect = NULL; onReceiveError = NULL; onSendError = NULL; } ~tagServerContext() { svrSock = INVALID_SOCKET; memset(&svrSockAddr, 0, sizeof(svrSockAddr)); bStart = FALSE; pVoid = NULL; onReceive = NULL; onSend = NULL; onClose = NULL; onConnect = NULL; onReceiveError = NULL; onSendError = NULL; } } SERVER_CONTEXT; // typedef map<void*, SERVER_CONTEXT*> OBJ_CONTEXT_MAP; typedef map<SOCKET, PER_IO_DATA*> SOCK_DATA_MAP; // class CLock { public: CLock(CRITICAL_SECTION& cs) : m_CS(cs) { EnterCriticalSection(&m_CS); } ~CLock() { LeaveCriticalSection(&m_CS); } private: CRITICAL_SECTION& m_CS; }; #define LOCK_CONTEXTS() / CLock lock(g_csMapObjContext); #define LOCK_SOCKDATA() / CLock lock(g_csMapSockData); // #define NOTIFY_CONNECT(pContext, sock, addr) / if (pContext->onConnect) / pContext->onConnect(pContext->pVoid, sock, addr); #define NOTIFY_CLOSE(pContext, sock, addr) / if (pContext->onClose) / pContext->onClose(pContext->pVoid, sock, addr); #define NOTIFY_RECEIVE(pContext, sock, addr, buf, length) / if (pContext->onReceive) / pContext->onReceive(pContext->pVoid, sock, addr, buf, length); #define NOTIFY_SEND(pContext, sock, addr, buf, length) / if (pContext->onSend) / pContext->onSend(pContext->pVoid, sock, addr, buf, length); #define NOTIFY_SEND_ERROR(pContext, sock, addr, error) / if (pContext->onSendError) / pContext->onSendError(pContext->pVoid, sock, addr, error); #define NOTIFY_RECEIVE_ERROR() // #endif // dllmain.cpp : Defines the entry point for the DLL application. #include <WinSock2.h> #include <MSWSock.h> #include <Windows.h> #pragma comment(lib, "ws2_32.lib") #include <iostream> using namespace std; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } // typedef void (*ON_RECEIVE_CALLBACK)(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); typedef void (*ON_RECEIVE_ERROR_CALLBACK)(int nError, SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_SEND_CALLBACK)(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); typedef void (*ON_SEND_ERROR_CALLBACK)(int nError, SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_CLOSE_CALLBACK)(SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_CONNECT_CALLBACK)(SOCKET sock, SOCKADDR_IN sockAddr); typedef struct tagServerContext { SOCKET svrSock; SOCKADDR_IN svrSockAddr; BOOL bStart; HANDLE hComplitionPort; ON_RECEIVE_CALLBACK onReceive; ON_SEND_CALLBACK onSend; ON_CLOSE_CALLBACK onClose; ON_CONNECT_CALLBACK onConnect; ON_RECEIVE_ERROR_CALLBACK onReceiveError; ON_SEND_ERROR_CALLBACK onSendError; tagServerContext() { bStart = FALSE; onReceive = NULL; onSend = NULL; onClose = NULL; onConnect = NULL; onReceiveError = NULL; onSendError = NULL; } } SERVER_CONTEXT; #define BUFFER_SIZE 4096 typedef struct _tagClientInfo { SOCKET sock; SOCKADDR_IN addrClient; } CLIENT_INFO; typedef struct _tagPerIoData { WSAOVERLAPPED overlapped; WSABUF buffer; char szBuf[BUFFER_SIZE]; int nBufLength; int nOperationType; DWORD dwNumberOfBytes; DWORD dwFlag; DWORD dwBytes; SOCKET sock; SOCKADDR_IN addrClient; } PER_IO_DATA; typedef enum { RECV_POSTED, SEND_POSTED, ACCEPT_POSTED } OPERATION_TYPE; #define NOTIFY_CONNECT(sock, addr) / if (g_svrContext.onConnect) / g_svrContext.onConnect(sock, addr); #define NOTIFY_CLOSE(sock, addr) / if (g_svrContext.onClose) / g_svrContext.onClose(sock, addr); #define NOTIFY_RECEIVE(sock, addr, buf, length) / if (g_svrContext.onReceive) / g_svrContext.onReceive(sock, addr, buf, length); #define NOTIFY_SEND() SERVER_CONTEXT g_svrContext; LPFN_ACCEPTEX lpfnAcceptEx; LPFN_GETACCEPTEXSOCKADDRS lpfnGetAcceptExSockaddrs; // int InitSocket(SOCKET& sock, SOCKADDR_IN& sockAddr, int nPort, int nListen) { sock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) return -1; sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); sockAddr.sin_port = htons(nPort); CLIENT_INFO* pClient = (CLIENT_INFO*)GlobalAlloc(GPTR, sizeof(CLIENT_INFO)); pClient->sock = sock; pClient->addrClient = sockAddr; CreateIoCompletionPort((HANDLE)sock, g_svrContext.hComplitionPort, (ULONG_PTR)pClient, 0); int nRet = bind(sock, (PSOCKADDR)&sockAddr, sizeof(sockAddr)); if (nRet == SOCKET_ERROR) return -1; nRet = listen(sock, nListen); if (nRet == SOCKET_ERROR) return -1; return 0; } int LoadExFunctions(const SOCKET& sock, LPFN_ACCEPTEX& pAcceptEx, LPFN_GETACCEPTEXSOCKADDRS& pGetAcceptExSockaddrs) { GUID guid = WSAID_ACCEPTEX; DWORD dwBytes; WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &pAcceptEx, sizeof(pAcceptEx), &dwBytes, NULL, NULL); GUID guid2 = WSAID_GETACCEPTEXSOCKADDRS; WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid2, sizeof(guid2), &pGetAcceptExSockaddrs, sizeof(pGetAcceptExSockaddrs), &dwBytes, NULL, NULL); return 0; } int PostAccept() { PER_IO_DATA* pIOData = (PER_IO_DATA*)GlobalAlloc(GPTR, sizeof(PER_IO_DATA)); memset(&pIOData->overlapped, 0, sizeof(OVERLAPPED)); pIOData->buffer.len = BUFFER_SIZE; pIOData->buffer.buf = pIOData->szBuf; pIOData->nOperationType = ACCEPT_POSTED; pIOData->nBufLength = BUFFER_SIZE; pIOData->sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, WSA_FLAG_OVERLAPPED); return lpfnAcceptEx(g_svrContext.svrSock, pIOData->sock, pIOData->szBuf, pIOData->nBufLength - ((sizeof(SOCKADDR_IN) + 16) * 2), sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, NULL, &pIOData->overlapped); } int PostReceive(PER_IO_DATA* pIOData) { memset(&pIOData->overlapped, 0, sizeof(OVERLAPPED)); memset(pIOData->szBuf, 0, BUFFER_SIZE); pIOData->nOperationType = RECV_POSTED; pIOData->dwFlag = 0; return WSARecv(pIOData->sock, &pIOData->buffer, 1, &pIOData->dwBytes, &pIOData->dwFlag, &pIOData->overlapped, NULL); } // DWORD WINAPI ServerThread(LPVOID lpVoid) { HANDLE hComplitionPort = (HANDLE)lpVoid; CLIENT_INFO* pClient; PER_IO_DATA* pIOData; DWORD dwCompletionBytes; while (TRUE) { BOOL bRet = GetQueuedCompletionStatus(hComplitionPort, &dwCompletionBytes, (DWORD*)&pClient, (LPOVERLAPPED*)&pIOData, INFINITE); if ((dwCompletionBytes == 0) && (pIOData->nOperationType == RECV_POSTED || pIOData->nOperationType == SEND_POSTED)) // Close connection here { NOTIFY_CLOSE(pClient->sock, pClient->addrClient); closesocket(pClient->sock); GlobalFree(pClient); GlobalFree(pIOData); continue; } if (pIOData->nOperationType == RECV_POSTED) // Receive done { NOTIFY_RECEIVE(pIOData->sock, pIOData->addrClient, pIOData->szBuf, dwCompletionBytes); PostReceive(pIOData); } else if (pIOData->nOperationType == ACCEPT_POSTED) { setsockopt(pIOData->sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&(pIOData->sock), sizeof(pIOData->sock)); int nLocalAddrLength = 0; int nRemoteAddrLength = 0; SOCKADDR_IN localAddr; lpfnGetAcceptExSockaddrs(pIOData->szBuf, pIOData->nBufLength - ((sizeof(SOCKADDR_IN) + 16) * 2), sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, (LPSOCKADDR*)&localAddr, &nLocalAddrLength, (LPSOCKADDR*)&pIOData->addrClient, &nRemoteAddrLength); pClient = (CLIENT_INFO*)GlobalAlloc(GPTR, sizeof(CLIENT_INFO)); pClient->sock = pIOData->sock; memcpy(&pClient->addrClient, &pIOData->addrClient, sizeof(SOCKADDR_IN)); CreateIoCompletionPort((HANDLE)pClient->sock, hComplitionPort, (ULONG_PTR)pClient, 0); NOTIFY_CONNECT(pClient->sock, pClient->addrClient); if (dwCompletionBytes > 0) NOTIFY_RECEIVE(pClient->sock, pClient->addrClient, pIOData->szBuf, dwCompletionBytes); PostReceive(pIOData); PostAccept(); } } return 0; } // void Test() { while (TRUE) { SOCKADDR_IN addrRemote; SOCKET sockRemote; int nSize = sizeof(addrRemote); sockRemote = WSAAccept(g_svrContext.svrSock, (PSOCKADDR)&addrRemote, &nSize, NULL, 0); CLIENT_INFO* pClient = (CLIENT_INFO*)GlobalAlloc(GPTR, sizeof(CLIENT_INFO)); pClient->sock = sockRemote; memcpy(&pClient->addrClient, &addrRemote, nSize); CreateIoCompletionPort((HANDLE)sockRemote, g_svrContext.hComplitionPort, (DWORD)pClient, 0); PER_IO_DATA* pIOData = (PER_IO_DATA*)GlobalAlloc(GPTR, sizeof(PER_IO_DATA)); memset(&pIOData->overlapped, 0, sizeof(OVERLAPPED)); pIOData->sock = sockRemote; pIOData->buffer.len = BUFFER_SIZE; pIOData->buffer.buf = pIOData->szBuf; pIOData->nBufLength = BUFFER_SIZE; PostReceive(pIOData); } } // extern "C" int __declspec(dllexport) SetCallbacks(ON_RECEIVE_CALLBACK onReceive, ON_SEND_CALLBACK onSend, ON_CONNECT_CALLBACK onConnect, ON_CLOSE_CALLBACK onClose, ON_RECEIVE_ERROR_CALLBACK onReceiveError, ON_SEND_ERROR_CALLBACK onSendError) { if (g_svrContext.bStart) return -1; g_svrContext.onReceive = onReceive; g_svrContext.onSend = onSend; g_svrContext.onConnect = onConnect; g_svrContext.onClose = onClose; g_svrContext.onReceiveError = onReceiveError; g_svrContext.onSendError = onSendError; return 0; } extern "C" int __declspec(dllexport) StartTCPServer(int nPort, int nListen) { if (g_svrContext.bStart) return -1; WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); g_svrContext.hComplitionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (g_svrContext.hComplitionPort == NULL) return -1; SYSTEM_INFO sysInfo; GetSystemInfo(&sysInfo); HANDLE* pHandles = new HANDLE[sysInfo.dwNumberOfProcessors]; for (unsigned int nItem = 0; nItem < sysInfo.dwNumberOfProcessors; nItem++) pHandles[nItem] = CreateThread(NULL, 0, ServerThread, g_svrContext.hComplitionPort, 0, NULL); if (InitSocket(g_svrContext.svrSock, g_svrContext.svrSockAddr, nPort, nListen) != 0) return -1; LoadExFunctions(g_svrContext.svrSock, lpfnAcceptEx, lpfnGetAcceptExSockaddrs); g_svrContext.bStart = TRUE; for (int nItem = 0; nItem < 100; nItem++) PostAccept(); //Test(); WaitForMultipleObjects(sysInfo.dwNumberOfProcessors, pHandles, TRUE, INFINITE); delete[] pHandles; PostQueuedCompletionStatus(g_svrContext.hComplitionPort, 0xFFFFFFFF, 0, NULL); CloseHandle(g_svrContext.hComplitionPort); closesocket(g_svrContext.svrSock); WSACleanup(); return 0; } extern "C" int __declspec(dllexport) ShutDownTCPServer() { //closesocket(g_svrContext.svrSock); //WSACleanup(); return 0; } extern "C" int __declspec(dllexport) Send(SOCKET sock, char* pBuf, int nLength) { if (!g_svrContext.bStart) return -1; return 0; } #ifndef _TCP_SERVER_H #define _TCP_SERVER_H #include <Windows.h> class CTCPServer { public: CTCPServer(int nPort, int nListenCount); virtual ~CTCPServer(); protected: CTCPServer() {} public: int Start(); int Stop(); public: void DoAccept(SOCKET sock, SOCKADDR_IN sockAddr); void DoReceive(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); void DoSend(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); void DoClose(SOCKET sock, SOCKADDR_IN sockAddr); void DoReceiveError(SOCKET sock, SOCKADDR_IN sockAddr, int nError); void DoSendError(SOCKET sock, SOCKADDR_IN sockAddr, int nError); protected: virtual void OnAccept(SOCKET sock, SOCKADDR_IN sockAddr); virtual void OnReceive(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); virtual void OnSend(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); virtual void OnClose(SOCKET sock, SOCKADDR_IN sockAddr); virtual void OnReceiveError(SOCKET sock, SOCKADDR_IN sockAddr, int nError); virtual void OnSendError(SOCKET sock, SOCKADDR_IN sockAddr, int nError); protected: static void OnReceiveCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); static void OnReceiveErrorCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, int nError); static void OnSendCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); static void OnSendErrorCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, int nError); static void OnCloseCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr); static void OnAcceptCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_RECEIVE_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); typedef void (*ON_RECEIVE_ERROR_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, int nError); typedef void (*ON_SEND_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); typedef void (*ON_SEND_ERROR_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, int nError); typedef void (*ON_CLOSE_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_CONNECT_CALLBACK)(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr); typedef int (*SetCallbacksFunc)(void* pVoid, ON_RECEIVE_CALLBACK, ON_SEND_CALLBACK, ON_CONNECT_CALLBACK, ON_CLOSE_CALLBACK, ON_RECEIVE_ERROR_CALLBACK, ON_SEND_ERROR_CALLBACK); typedef int (*StartTCPServerFunc)(void*, int, int); typedef int (*ShutDownTCPServerFunc)(void*); typedef int (*SendFunc)(void*, SOCKET, char*, int); SendFunc Send; SetCallbacksFunc SetCallbacks; StartTCPServerFunc StartTCPServer; ShutDownTCPServerFunc ShutDownTCPServer; protected: bool m_bStart; int m_nPort; int m_nListenCount; HINSTANCE m_hDll; }; #endif #include "TCPServer.h" #include <iostream> using namespace std; CTCPServer::CTCPServer(int nPort, int nListenCount) : m_bStart(false), m_nPort(nPort), m_nListenCount(nListenCount), m_hDll(NULL) { } CTCPServer::~CTCPServer() { } // void CTCPServer::OnReceiveCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength) { CTCPServer* pServer = (CTCPServer*)pVoid; if (pServer == NULL) return; pServer->DoReceive(sock, sockAddr, pBuffer, nLength); } void CTCPServer::OnReceiveErrorCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, int nError) { CTCPServer* pServer = (CTCPServer*)pVoid; if (pServer == NULL) return; pServer->DoReceiveError(sock, sockAddr, nError); } void CTCPServer::OnSendCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength) { CTCPServer* pServer = (CTCPServer*)pVoid; if (pServer == NULL) return; pServer->DoSend(sock, sockAddr, pBuffer, nLength); } void CTCPServer::OnSendErrorCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr, int nError) { CTCPServer* pServer = (CTCPServer*)pVoid; if (pServer == NULL) return; pServer->DoSendError(sock, sockAddr, nError); } void CTCPServer::OnCloseCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr) { CTCPServer* pServer = (CTCPServer*)pVoid; if (pServer == NULL) return; pServer->DoClose(sock, sockAddr); } void CTCPServer::OnAcceptCallback(void* pVoid, SOCKET sock, SOCKADDR_IN sockAddr) { CTCPServer* pServer = (CTCPServer*)pVoid; if (pServer == NULL) return; pServer->DoAccept(sock, sockAddr); } // int CTCPServer::Start() { m_hDll = LoadLibrary("IOCPTcp.dll"); if (m_hDll == NULL) return -1; SetCallbacks = (SetCallbacksFunc)GetProcAddress(m_hDll, "SetCallbacks"); StartTCPServer = (StartTCPServerFunc)GetProcAddress(m_hDll, "StartTCPServer"); ShutDownTCPServer = (ShutDownTCPServerFunc)GetProcAddress(m_hDll, "ShutDownTCPServer"); Send = (SendFunc)GetProcAddress(m_hDll, "Send"); SetCallbacks((void*)this, CTCPServer::OnReceiveCallback, CTCPServer::OnSendCallback, CTCPServer::OnAcceptCallback, CTCPServer::OnCloseCallback, CTCPServer::OnReceiveErrorCallback, CTCPServer::OnSendErrorCallback); return StartTCPServer((void*)this, m_nPort, m_nListenCount); } int CTCPServer::Stop() { ShutDownTCPServer((void*)this); FreeLibrary(m_hDll); return 0; } // void CTCPServer::DoAccept(SOCKET sock, SOCKADDR_IN sockAddr) { OnAccept(sock, sockAddr); } void CTCPServer::DoReceive(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength) { OnReceive(sock, sockAddr, pBuffer, nLength); } void CTCPServer::DoSend(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength) { OnSend(sock, sockAddr, pBuffer, nLength); } void CTCPServer::DoClose(SOCKET sock, SOCKADDR_IN sockAddr) { OnClose(sock, sockAddr); } void CTCPServer::DoReceiveError(SOCKET sock, SOCKADDR_IN sockAddr, int nError) { OnReceiveError(sock, sockAddr, nError); } void CTCPServer::DoSendError(SOCKET sock, SOCKADDR_IN sockAddr, int nError) { OnSendError(sock, sockAddr, nError); } // void CTCPServer::OnAccept(SOCKET sock, SOCKADDR_IN sockAddr) { cout << this <<" SOCKET: " << sock << " connected" << endl; } void CTCPServer::OnReceive(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength) { cout << this << " OnReceive get data: " << pBuffer << endl; } void CTCPServer::OnSend(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength) { cout << "OnSend send: " << pBuffer << endl; } void CTCPServer::OnClose(SOCKET sock, SOCKADDR_IN sockAddr) { cout << "SOCKET: " << sock << " closed" << endl; } void CTCPServer::OnReceiveError(SOCKET sock, SOCKADDR_IN sockAddr, int nError) { cout << "OnReceiveError get error: " << nError << endl; } void CTCPServer::OnSendError(SOCKET sock, SOCKADDR_IN sockAddr, int nError) { cout << "OnSendError get error: " << nError << endl; } Test.cpp #include <Windows.h> #include <iostream> using namespace std; // void OnReceive(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength) { cout << "OnReceive get data: " << pBuffer << endl; } void OnReceiveError(int nError, SOCKET sock, SOCKADDR_IN sockAddr) { cout << "OnReceiveError get error: " << nError << endl; } void OnSend(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength) { cout << "OnSend send: " << pBuffer << endl; } void OnSendError(int nError, SOCKET sock, SOCKADDR_IN sockAddr) { cout << "OnSendError get error: " << nError << endl; } void OnClose(SOCKET sock, SOCKADDR_IN sockAddr) { cout << "SOCKET: " << sock << " closed" << endl; } void OnConnect(SOCKET sock, SOCKADDR_IN sockAddr) { cout << "SOCKET: " << sock << " connected" << endl; } // typedef void (*ON_RECEIVE_CALLBACK)(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); typedef void (*ON_RECEIVE_ERROR_CALLBACK)(int nError, SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_SEND_CALLBACK)(SOCKET sock, SOCKADDR_IN sockAddr, char* pBuffer, int nLength); typedef void (*ON_SEND_ERROR_CALLBACK)(int nError, SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_CLOSE_CALLBACK)(SOCKET sock, SOCKADDR_IN sockAddr); typedef void (*ON_CONNECT_CALLBACK)(SOCKET sock, SOCKADDR_IN sockAddr); typedef int (*SetCallbacksFunc)(ON_RECEIVE_CALLBACK, ON_SEND_CALLBACK, ON_CONNECT_CALLBACK, ON_CLOSE_CALLBACK, ON_RECEIVE_ERROR_CALLBACK, ON_SEND_ERROR_CALLBACK); typedef int (*StartTCPServerFunc)(int, int); typedef int (*ShutDownTCPServerFunc)(); // DWORD WINAPI ServerThread(LPVOID lpVoid) { HINSTANCE hDll = (HINSTANCE)lpVoid; SetCallbacksFunc SetCallbacks = (SetCallbacksFunc)GetProcAddress(hDll, "SetCallbacks"); StartTCPServerFunc StartTCPServer = (StartTCPServerFunc)GetProcAddress(hDll, "StartTCPServer"); ShutDownTCPServerFunc ShutDownTCPServer = (ShutDownTCPServerFunc)GetProcAddress(hDll, "ShutDownTCPServer"); SetCallbacks(OnReceive, OnSend, OnConnect, OnClose, OnReceiveError, OnSendError); cout << "Start server......" << endl; StartTCPServer(5054, 5); cout << "Server shutdown" << endl; return 0; } // int _tmain(int argc, _TCHAR* argv[]) { HINSTANCE hServerDll = LoadLibrary("IOCPTcp.dll"); if (hServerDll == NULL) return -1; cout << "Load IOCPTcp.dll done" << endl; cout << "Prepare to start TCP server" << endl; HANDLE hThread = CreateThread(NULL, 0, ServerThread, hServerDll, 0, NULL); WaitForSingleObject(hThread, INFINITE); cout << "EXIT" << endl; return 0; }