|
#ifdef _DEBUG
#define GMT_ASSERT(exp) assert(exp) #else #define GMT_ASSERT(exp) #endif #define PORT 5150
#define DATA_BUFSIZE 8192 // Overlapped event.
#define RECV_WSAEVENT 0 #define SEND_WSAEVENT 1 #define CTRL_IOTHREAD_WSAEVENT 2 #define WSAEVENT_COUNT 3 // Index of thread type.
#define SEND_THREAD 0 #define IO_THREAD 1 #define THREAD_COUNT 2 typedef struct _SOCKET_INFORMATION {
char szIOBuffer[DATA_BUFSIZE]; WSABUF DataBuf; WSAOVERLAPPED Overlapped; DWORD BytesSEND; DWORD BytesRECV; } SOCKET_INFORMATION, * LPSOCKET_INFORMATION; SOCKET ClientSocket;
DWORD EventTotal = 0; HANDLE hThread[THREAD_COUNT]; WSAEVENT EventArray[WSAEVENT_COUNT]; LPSOCKET_INFORMATION g_pSIRecv = NULL; LPSOCKET_INFORMATION g_pSISend = NULL; void CloseClientSocket()
{ if (INVALID_SOCKET != ClientSocket) { if (closesocket(ClientSocket) == 0) ClientSocket = INVALID_SOCKET; } } // Deliver recv operation.
int RecvData() { if (NULL == g_pSIRecv || INVALID_SOCKET == ClientSocket) return FALSE; DWORD dwFlags = 0;
g_pSIRecv->BytesRECV = 0; memset(g_pSIRecv->szIOBuffer, 0, sizeof(g_pSIRecv->szIOBuffer)); g_pSIRecv->DataBuf.len = sizeof(g_pSIRecv->szIOBuffer)-1; int nRet = WSARecv(ClientSocket, &(g_pSIRecv->DataBuf), 1, &g_pSIRecv->BytesRECV, &dwFlags, &(g_pSIRecv->Overlapped), NULL); if (nRet == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d/n", WSAGetLastError()); CloseClientSocket(); return FALSE; } } return TRUE;
} // Deliver send operation.
BOOL SendData() { if (NULL == g_pSIRecv || INVALID_SOCKET == ClientSocket) return FALSE; g_pSISend->BytesSEND = 0;
strcpy(g_pSISend->szIOBuffer, "this is client data."); g_pSISend->DataBuf.len = strlen(g_pSISend->szIOBuffer); int nRet = WSASend(ClientSocket, &(g_pSISend->DataBuf), 1, &g_pSISend->BytesSEND, 0, &(g_pSISend->Overlapped), NULL); if (nRet == SOCKET_ERROR) { if (WSAGetLastError() != ERROR_IO_PENDING) { printf("WSASend() failed with error %d/n", WSAGetLastError()); CloseClientSocket(); return FALSE; } } return TRUE;
} unsigned __stdcall SendThreadFunc( void* pArguments )
{ printf("Send thread is running .../r/n"); while(TRUE)
{ if (!SendData()) break; Sleep(1000);
} if (WSA_INVALID_EVENT != EventArray[2])
{ WSASetEvent(EventArray[2]); EventArray[2] = WSA_INVALID_EVENT; } printf("SendThreadFunc is over./r/n");
return 0;
} unsigned __stdcall IOThreadFunc( void* pArguments )
{ printf("IO thread is running .../r/n"); DWORD dwEventIndex = 0;
DWORD dwFlags = 0; DWORD BytesTransferred = 0; LPSOCKET_INFORMATION pSI = NULL; // Process asynchronous WSASend, WSARecv requests.
while(TRUE) { // Wait overlapped I/O event. dwEventIndex = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE); GMT_ASSERT(dwEventIndex < 3); if ( dwEventIndex == WSA_WAIT_FAILED) { printf("WSAWaitForMultipleEvents failed %d/n", WSAGetLastError()); break; } WSAResetEvent(EventArray[dwEventIndex - WSA_WAIT_EVENT_0]);
if (dwEventIndex - WSA_WAIT_EVENT_0 == RECV_WSAEVENT)
pSI = g_pSIRecv; // Recv event is signaled. else if (dwEventIndex - WSA_WAIT_EVENT_0 == SEND_WSAEVENT) pSI = g_pSISend; // Send event is signaled. else if (dwEventIndex - WSA_WAIT_EVENT_0 == CTRL_IOTHREAD_WSAEVENT) break; // IO thread Control event is signaled, exit. GMT_ASSERT(NULL != pSI);
// I/O operation is completed.
dwFlags = 0; BytesTransferred = 0; BOOL bRet = WSAGetOverlappedResult(ClientSocket, &(pSI->Overlapped), &BytesTransferred, TRUE, &dwFlags); if ( !bRet) { printf("WSAGetOverlappedResult error code: %d/r/n", WSAGetLastError()); break; } if (0 == BytesTransferred)
{ printf("IO Bytes is 0, error code is %d /r/n", WSAGetLastError()); break; } if (dwEventIndex - WSA_WAIT_EVENT_0 == 0) // Recv data successfully.
{ printf("recv data: [%d]%s/r/n", BytesTransferred, pSI->szIOBuffer); } else if (dwEventIndex - WSA_WAIT_EVENT_0 == 1) // Send data successfully. { // printf("send data successfully ... /r/n"); } // Deliver recv operation.
if (!RecvData()) break; } CloseClientSocket();
for (int i=0; i<EventTotal; i++)
{ if (WSA_INVALID_EVENT != EventArray[i]) { WSACloseEvent(EventArray[i]); EventArray[i] = WSA_INVALID_EVENT; } } delete g_pSIRecv;
g_pSIRecv = NULL; delete g_pSISend;
g_pSISend = NULL; WSACleanup();
printf("IOThread is over./r/n");
return 0;
} BOOL InitializeSocket(LPCTSTR lpServerIp, DWORD dwServerPort)
{ WSADATA wsaData; SOCKET AcceptSocket; int nRet; if ((nRet = WSAStartup(0x0202,&wsaData)) != 0)
{ printf("WSAStartup failed with error %d/n", nRet); WSACleanup(); return FALSE; } ClientSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (INVALID_SOCKET == ClientSocket) { printf("WSASocket call failed with error: %ld/n", WSAGetLastError()); WSACleanup(); return FALSE; } // Connect to server.
SOCKADDR_IN AddrServer; AddrServer.sin_family = AF_INET; AddrServer.sin_addr.s_addr = inet_addr(lpServerIp); AddrServer.sin_port = htons(dwServerPort); nRet = connect( ClientSocket, (struct sockaddr*)(&AddrServer), sizeof(SOCKADDR_IN) ); if ( nRet == SOCKET_ERROR) { printf( "Failed to connect. Error Code: %d/n", WSAGetLastError()); WSACleanup(); return FALSE; } else { printf("connect to server successfully./r/n"); } for (EventTotal=0; EventTotal<WSAEVENT_COUNT; EventTotal++)
{ EventArray[EventTotal] = WSACreateEvent(); if (EventArray[EventTotal] == WSA_INVALID_EVENT) { printf("WSACreateEvent failed with error %d/n", WSAGetLastError()); WSACleanup(); return FALSE; } } g_pSIRecv = new SOCKET_INFORMATION;
ZeroMemory(&(g_pSIRecv->Overlapped), sizeof(WSAOVERLAPPED)); g_pSIRecv->Overlapped.hEvent = EventArray[RECV_WSAEVENT]; g_pSIRecv->DataBuf.len = sizeof(g_pSIRecv->szIOBuffer)-1; g_pSIRecv->DataBuf.buf = g_pSIRecv->szIOBuffer; memset(g_pSIRecv->szIOBuffer, 0, sizeof(g_pSIRecv->szIOBuffer)); g_pSISend = new SOCKET_INFORMATION;
ZeroMemory(&(g_pSISend->Overlapped), sizeof(WSAOVERLAPPED)); g_pSISend->Overlapped.hEvent = EventArray[SEND_WSAEVENT]; g_pSISend->DataBuf.len = sizeof(g_pSISend->szIOBuffer)-1; g_pSISend->DataBuf.buf = g_pSISend->szIOBuffer; memset(g_pSISend->szIOBuffer, 0, sizeof(g_pSISend->szIOBuffer)); // Create a thread to service overlapped requests
unsigned threadID; printf( "Creating 2 thread.../n" );
// Create the IO thread.
hThread[IO_THREAD] = (HANDLE)_beginthreadex( NULL, 0, &IOThreadFunc, NULL, 0, &threadID ); if (hThread[IO_THREAD] == NULL) { printf("CreateThread failed with error %d/n", GetLastError()); WSACleanup(); return FALSE; } // Create the send thread.
hThread[SEND_THREAD] = (HANDLE)_beginthreadex( NULL, 0, &SendThreadFunc, NULL, CREATE_SUSPENDED, &threadID ); if (hThread[SEND_THREAD] == NULL) { printf("CreateThread failed with error %d/n", GetLastError()); WSACleanup(); return FALSE; } CloseHandle(hThread[IO_THREAD]);
CloseHandle(hThread[SEND_THREAD]); return TRUE;
} //
// @ret success 0 // fail -1 OVERLAPPEDIOCLIENT_API int SendData(LPCTSTR lpData) { int nEndRet = 0;
if (NULL == lpData)
{ return -1; } // callee count.
static DWORD dwSndCount = 0; if (0 == dwSndCount) { ResumeThread(hThread[IO_THREAD]); ResumeThread(hThread[SEND_THREAD]); } dwSndCount++; if (NULL == g_pSISend)
return -1; memset(g_pSISend->szIOBuffer, 0, sizeof(g_pSISend->szIOBuffer));
strcpy(g_pSISend->szIOBuffer, lpData); g_pSISend->DataBuf.len = strlen(g_pSISend->szIOBuffer); return SendData();
} // Set sending file and recving file, listen ip and port. // @para lpRecvFile recv file path. // lpServerIp NULL any ip or specified ip. // dwPort listen port. // dwRecvInterval Recv operation time interval. // @ret -1 fail. // 0 success OVERLAPPEDIOCLIENT_API int SetClient(LPCTSTR lpRecvFile, LPCTSTR lpServerIp, DWORD dwServerPort, DWORD dwRecvInternal) { GMT_ASSERT(lpRecvFile != NULL); GMT_ASSERT(lpServerIp != NULL); return InitializeSocket(lpServerIp, dwServerPort); } // using
dllmodule=LoadLibrary("OverLappedIOClient.dll"); if (NULL == dllmodule) { DWORD dwErr = GetLastError(); cout <<"LoadLibrary failed!" << "error code:" << dwErr << endl; } PFSETCLIENT pfSetClient = (PFSETCLIENT)GetProcAddress(dllmodule,"SetClient");
if (NULL == pfSetClient) { DWORD dwErr = GetLastError(); cout <<"GetProcAddress(dllmodule,SetClient) failed! "<< "error code:" << dwErr << endl; FreeLibrary(dllmodule); return -1; } LPCTSTR lpRecvFile = "D://VC2005Project//ConselCodeTest//debug//ClientRecvFile.txt";
if (!pfSetClient(lpRecvFile, "127.0.0.1", 5150, 2000)) { FreeLibrary(dllmodule); return -1; } PSEND pfSend = (PSEND)GetProcAddress(dllmodule,"SendData"); if (NULL == pfSend) { DWORD dwErr = GetLastError(); cout <<"GetProcAddress(dllmodule,Send) failed!"<< "error code:" << dwErr << endl; FreeLibrary(dllmodule); return -1; } int nCount = 0; string str;
DWORD dwSend; str = "this is test data"; while (TRUE) { LPCTSTR lpData = str.data(); if (str == "stop") { lpData = NULL; dwSend = 0; } else dwSend = strlen(lpData); if (-1 == pfSend(lpData)) break; Sleep(1000); } str.clear();
FreeLibrary(dllmodule); return 0;
|
本文详细介绍了如何利用重叠I/O技术来构建一个高性能的Socket客户端。通过这种方式,可以实现非阻塞的I/O操作,提高并发处理能力。文章涵盖了重叠I/O的概念、Windows平台下的完成端口(IOCP)使用,以及如何结合线程池来处理异步事件。
1138

被折叠的 条评论
为什么被折叠?



