IOCP示例问题
- C/C++ code
// iocpServ.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"/*** iocpSerc.c*/#include <stdio.h>#include <windows.h>#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")#define TCP_PORT 5150#define DATA_BUFSIZE 8192typedef struct{ OVERLAPPED Overlapped; WSABUF DataBuffer; CHAR Buffer[DATA_BUFSIZE]; DWORD BytesRecv; DWORD BytesSend;}PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA; typedef struct { SOCKET Socket; }PER_HANDLE_DATA, * LPPER_HANDLE_DATA; DWORD WINAPI ServerWorkerThread(LPVOID); void main(void) { WSADATA wsaData; SOCKADDR_IN InternetAddr; SOCKET ListenSocket; SOCKET AcceptSocket; LPPER_HANDLE_DATA perHandleData; LPPER_IO_OPERATION_DATA perIoData; HANDLE CompletionPort; // HANDLE hThread; DWORD RecvBytes; DWORD ThreadId; SYSTEM_INFO SystemInfo; DWORD Ret; DWORD Flags; int i; // 加载winsock2.2 Ret = WSAStartup(0x0202, &wsaData); // Ret = WSAStartup(MAKEWORD(2,2), &wsaData) if(0 != Ret) { printf("WSAStartup failed with error%d\n", Ret); return; } // 创建一个完成端口 CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if(NULL == CompletionPort) { printf("CreateIoCompletionPort() failed with error%d\n", GetLastError()); return; } // 查看系统处理器个数 GetSystemInfo(&SystemInfo); // 根据系统现有的处理器创建合理的线程数 for(i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++) { HANDLE hThread; // 创建一个线程,把完成端口传递给它 hThread = CreateThread(NULL, 0, ServerWorkerThread, CompletionPort, 0, &ThreadId); if(NULL == hThread) { printf("CreateThread() failed with error%d\n", GetLastError()); return; } // 关闭线程 CloseHandle(hThread); } // 创建一个套接字 ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if(INVALID_SOCKET == ListenSocket) { printf("WSASocket() failed with error%d\n", WSAGetLastError()); return; } InternetAddr.sin_family = AF_INET; InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY); InternetAddr.sin_port = htons(TCP_PORT); //绑定套接字 if(SOCKET_ERROR == bind(ListenSocket, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr))) { printf("bind() faile with error%d\n", WSAGetLastError()); return; } //监听套接字 if(SOCKET_ERROR == listen(ListenSocket, 5)) { printf("listen() failed with error%d\n", WSAGetLastError()); return; } // 接受socket,并把它与完成端口关联 while(TRUE) { AcceptSocket = WSAAccept(ListenSocket, NULL, NULL, NULL, 0); if(SOCKET_ERROR == AcceptSocket) { printf("WSAAccept() failed with error%d\n", WSAGetLastError()); return; } perHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(LPPER_HANDLE_DATA)); if(NULL == perHandleData) { printf("GlobalAlloc() failed with error %d\n", GetLastError()); return; } printf("Socket number %d connect\n", AcceptSocket); perHandleData->Socket = AcceptSocket; if(NULL == CreateIoCompletionPort((HANDLE)AcceptSocket, CompletionPort, (DWORD)perHandleData, 0)) { printf("CreateIoCompletionPort() failed with error %d\n", GetLastError()); return; } perIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(LPPER_IO_OPERATION_DATA)); if(NULL == perIoData) { printf("GlobalAlloc() failed with error %d\n", GetLastError()); return; } ZeroMemory(&(perIoData->Overlapped), sizeof(OVERLAPPED)); [color=#FF0000]perIoData->BytesRecv = 0;[/color] perIoData->BytesSend = 0; perIoData->DataBuffer.len = DATA_BUFSIZE; perIoData->DataBuffer.buf = perIoData->Buffer; Flags = 0; if(SOCKET_ERROR == WSARecv(AcceptSocket, &(perIoData->DataBuffer), 1, &(RecvBytes), &Flags, &(perIoData->Overlapped), NULL)) { if(WSAGetLastError() != ERROR_IO_PENDING) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return; } } } } DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID){ HANDLE CompletionPort = (HANDLE)CompletionPortID; DWORD BytesTransferred; LPOVERLAPPED Overlapped; LPPER_IO_OPERATION_DATA perIoData; LPPER_HANDLE_DATA perHandleData; DWORD SendBytes, RecyBytes; DWORD Flags; while(TRUE) { if(GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&perHandleData, (LPOVERLAPPED *)&perIoData, INFINITE) == 0) { printf("GetQueuedCompletionStatus() failed with error %d\n", GetLastError()); return 0; } if(0 == BytesTransferred) { printf("Closing socket %d\n", perHandleData->Socket); if(SOCKET_ERROR == closesocket(perHandleData->Socket)) { printf("closesocket() failed with error %d\n"), WSAGetLastError(); return 0; } GlobalFree(perHandleData); GlobalFree(perIoData); continue; } if(0 == perIoData->BytesRecv) { perIoData->BytesRecv = BytesTransferred; perIoData->BytesSend = 0;printf("BytesRecv:%s\n", perIoData->BytesRecv); } else { perIoData->BytesSend += BytesTransferred;printf("BytesSend:%s\n", perIoData->BytesSend); } if(perIoData->BytesRecv > perIoData->BytesSend) { ZeroMemory(&(perIoData->Overlapped), sizeof(OVERLAPPED)); perIoData->DataBuffer.buf = perIoData->Buffer + perIoData->BytesSend; perIoData->DataBuffer.len = perIoData->BytesRecv - perIoData->BytesSend; if(SOCKET_ERROR == WSASend(perHandleData->Socket, &(perIoData->DataBuffer), 1, &SendBytes, 0, &(perIoData->Overlapped), NULL)) { if(ERROR_IO_PENDING != WSAGetLastError()) { printf("WSASend() failed with error %d\n", WSAGetLastError()); return 0; } } } else { perIoData->BytesRecv = 0; Flags = 0; ZeroMemory(&(perIoData->Overlapped), sizeof(OVERLAPPED)); perIoData->DataBuffer.len = DATA_BUFSIZE; perIoData->DataBuffer.buf = perIoData->Buffer; if(SOCKET_ERROR == WSARecv(perHandleData->Socket, &(perIoData->DataBuffer), 1, &RecyBytes, &Flags, &(perIoData->Overlapped), NULL)) { if(ERROR_IO_PENDING != WSAGetLastError()) { printf("WSARecv() failed with error %d\n", WSAGetLastError()); return 0; } } } }}
在上述红色处报有问题:
DataBufferf -buf0x00040003 <错误的指针>char *
BytesRecvCXX0030: 错误: 无法计算表达式的值
BytesSendCXX0030: 错误: 无法计算表达式的值
[解决办法]
"perIoData= (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR,sizeof(LPPER_IO_OPERATION_DATA));"
改成如下:
perIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
[解决办法]
参照我这个看看!
http://blog.csdn.net/jasonM2008/archive/2009/08/13/4441514.aspx