重叠 io 有一个函数,如果失败,那么需要再次调用,它叫什么啊?
重叠io winscock中的
今天看了msdn, 后来出去办点事,回来后,就发现再也找不到这个函数,找了一晚上,也没有找到。悲剧不?
问题2:
在大家的基础上和msdn的帮助, 我已经修改了代码,发现收到的数据会乱码,而且不断的输入,似乎是死循环的方式
打印数据,崩溃了
- C/C++ code
// NetWork.cpp : Defines the entry point for the console application.//#include"stdafx.h"#include"InitSock.h"#include <Winsock2.h>#include <Windows.h>#include <process.h>#pragma comment(lib, "WS2_32.lib")#define MAX_BUFFER 256#define MAX_TIMEOUT 4000typedef enum _OPERATION_INFO{ OP_NULL, OP_ACCEPT, OP_READ, OP_WRITE}OPERATIONINFO;typedef struct _OVERLAPPED_INFO_{ public: _OVERLAPPED_INFO_() { Clean(); } ~_OVERLAPPED_INFO_() { Clean(); }protected: void Clean() { ol.hEvent = NULL; sock = INVALID_SOCKET; wsaBuf.buf = szBuf; wsaBuf.len = MAX_BUFFER; memset(szBuf, 0, sizeof(szBuf)); }public: WSAOVERLAPPED ol; SOCKET sock; WSABUF wsaBuf; char szBuf[MAX_BUFFER];}OVERLAPPEDINFO, *POVERLAPPEDINFO;WSAEVENT g_event[WSA_MAXIMUM_WAIT_EVENTS] = {0};OVERLAPPEDINFO* g_ol[WSA_MAXIMUM_WAIT_EVENTS] = {0};int g_nIndex = 0;BOOL g_bExitThread = FALSE;unsigned __stdcall ThreadProc(LPVOID lParam);CInitSock g_InitSock;SOCKET g_sListen ;#include <stdio.h>#include <process.h>int main(){ g_sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(INVALID_SOCKET == g_sListen) { printf("socket failed with error code: %d/n", WSAGetLastError()); return EXIT_FAILURE; } SOCKADDR_IN addr = {0}; addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addr.sin_family = AF_INET; addr.sin_port = htons(5050); if(SOCKET_ERROR == bind(g_sListen, (LPSOCKADDR)&addr, sizeof(addr))) { printf("bind failed with error code: %d/n", WSAGetLastError()); closesocket(g_sListen); return EXIT_FAILURE; } if(SOCKET_ERROR == listen(g_sListen, 5)) { printf("listen failed with error code: %d/n", WSAGetLastError()); closesocket(g_sListen); return EXIT_FAILURE; } //g_ol[g_nIndex] = new OVERLAPPEDINFO; //g_ol[g_nIndex]->sock = g_sListen; //g_event[g_nIndex] = g_ol[g_nIndex]->ol.hEvent = WSACreateEvent(); //g_nIndex++; u_long argp=1; ioctlsocket(g_sListen,FIONBIO,&argp); HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, 0, NULL); if(NULL == hThread) { printf("_beginthreadex failed with error code: %d/n", GetLastError()); closesocket(g_sListen); return EXIT_FAILURE; } printf("Server start listen and wait for client to connect .../n"); WaitForSingleObject(hThread, INFINITE); g_bExitThread = TRUE; // Exit thread. CloseHandle(hThread); return 0;}unsigned __stdcall ThreadProc(LPVOID lParam){ while(!g_bExitThread) { DWORD dwFlags, dwTrans, BytesTransferred; dwFlags=0; SOCKADDR_IN remote = {0}; int len = sizeof(remote); SOCKET sNew=accept(g_sListen,(LPSOCKADDR)&remote,&len); if(INVALID_SOCKET !=sNew) { g_ol[g_nIndex]=new OVERLAPPEDINFO; g_ol[g_nIndex]->sock=sNew; g_event[g_nIndex]=g_ol[g_nIndex]->ol.hEvent=WSACreateEvent(); g_nIndex++; } for(int nPos=0; nPos<g_nIndex; nPos++) { //投递请求 if(SOCKET_ERROR == WSARecv(g_ol[nPos]->sock, &(g_ol[nPos]->wsaBuf), 1, &dwTrans, &dwFlags, &(g_ol[nPos]->ol), NULL)) { if(ERROR_IO_PENDING != WSAGetLastError()) { closesocket(g_ol[nPos]->sock); printf("WSARecv failed with error code: %d/n", WSAGetLastError()); continue; } } //等待事件对象触发 DWORD nRet = WSAWaitForMultipleEvents(1, &g_event[g_nIndex], TRUE, MAX_TIMEOUT, FALSE); if(WSA_WAIT_FAILED == nRet || WSA_WAIT_TIMEOUT == nRet) { continue; } //查询 BOOL bResult =WSAGetOverlappedResult(g_ol[nPos]->sock,&(g_ol[nPos]->ol), &BytesTransferred, FALSE, &dwFlags); if (bResult == FALSE) { wprintf(L"WSAGetOverlappedResult failed with error = %d\n", WSAGetLastError()); } //----------------------------------------- // If the connection has been closed, close the accepted socket if (BytesTransferred == 0) { closesocket(g_ol[nPos]->sock); WSACloseEvent(g_event[nPos]); } else { printf("%s\n",g_ol[nPos]->szBuf); } } } printf("Server to exit ... /n"); return 0;}
BOOL WSAAPI WSAGetOverlappedResult(
_In_ SOCKET s,
_In_ LPWSAOVERLAPPED lpOverlapped,
_Out_ LPDWORD lpcbTransfer,
_In_ BOOL fWait,
_Out_ LPDWORD lpdwFlags //这个参数,到底如何正确使用!!!! msdn说的过于含糊了,我发现其的值貌似是WSARecv的一个参数的值,是不是这样的啊???
);
[解决办法]
http://www.cnblogs.com/my_life/articles/1982091.html
可以看看文章,能增加你的理解.
[解决办法]
几年前封装过overlapped io socket模型.很高效的异步.
下面给你我学习用的例子. 这个是基于完成例程的重叠io.
- C/C++ code
#include "stdafx.h"#include <iostream>#include <tchar.h>#include <WINSOCK2.H>#include <stdio.h>#pragma comment(lib, "ws2_32.lib")#define MSGSIZE 1024#define PORT 10000typedef struct{ WSAOVERLAPPED overlap; WSABUF Buffer; char szMessage[MSGSIZE];// DWORD NumberOfBytesRecvd; DWORD Flags; SOCKET sClient;}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;void CALLBACK CompletionROUTINE(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags){ LPPER_IO_OPERATION_DATA lpPerIOData = (LPPER_IO_OPERATION_DATA)lpOverlapped; SOCKET sock=lpPerIOData->sClient; if (dwError != 0 || cbTransferred == 0) { // Connection was closed by client closesocket(lpPerIOData->sClient); printf("一个客户退出 socket id:%d\r\n",lpPerIOData->sClient); //释放客户对应的结构内存 delete lpPerIOData; lpPerIOData=NULL; } else { printf("recv sock:%d size:%d\n",sock,cbTransferred); //在这里处理接收的数据,然后发送...并重置这个客户socket异步接收操作.. //lpPerIOData->szMessage[cbTransferred] = '\0'; //send(lpPerIOData->sClient, lpPerIOData->szMessage, cbTransferred, 0); // Launch another asynchronous operation memset(&lpPerIOData->overlap, 0, sizeof(WSAOVERLAPPED)); lpPerIOData->Buffer.len = MSGSIZE; lpPerIOData->Buffer.buf = lpPerIOData->szMessage; WSARecv(lpPerIOData->sClient, &lpPerIOData->Buffer, 1, &lpPerIOData->NumberOfBytesRecvd, &lpPerIOData->Flags, &lpPerIOData->overlap, CompletionROUTINE); }}void GetError(DWORD error) //返回错误信息{ switch(error) { case WSANOTINITIALISED: printf("初始化错误\r\n"); break; case WSAENOTCONN: printf("对方没有启动\r\n"); break; case WSAEWOULDBLOCK : printf("对方已经关闭\r\n"); break; case WSAECONNREFUSED: printf("对方没打开端口\r\n"); break; case WSAENOTSOCK: printf("在一个非套接字上尝试了一个操作\r\n"); break; case WSAEADDRINUSE: printf("特定的地址已在使用中\r\n"); break; case WSAECONNRESET: printf("与主机的连接被关闭\r\n"); break; default: printf("一般错误,连接出现异常断开\r\n"); }}int main(){ WSADATA wsaData; SOCKET sListen; SOCKADDR_IN local, client; int iaddrSize = sizeof(SOCKADDR_IN); // Initialize Windows Socket library int ret= WSAStartup(0x0202, &wsaData); if(ret!=0) { printf("socket WSAStartup Error!\r\n"); return 1; }else printf("socket WSAStartup OK!\r\n"); // Create listening socket sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); local.sin_addr.S_un.S_addr = htonl(INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons(PORT); //绑定一个套接字到本机的地址 ret= bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN)); if(ret == SOCKET_ERROR) { //绑定错误 printf("Binding Error\r\n"); return FALSE; } // Listen ret= listen(sListen, 3); if(ret==SOCKET_ERROR) { printf("listen失败 错误原因:",ret=WSAGetLastError()); GetError(ret); return false ; } printf("listen OK!\r\nWaiting Client Connect\n"); while (TRUE) { // Accept a connection LPPER_IO_OPERATION_DATA lpPerIOData = NULL; SOCKET g_sNewClientConnection; g_sNewClientConnection = accept(sListen, (struct sockaddr *)&client, &iaddrSize); // Launch an asynchronous operation for new arrived connection lpPerIOData=new PER_IO_OPERATION_DATA(); lpPerIOData->Buffer.len = MSGSIZE; lpPerIOData->Buffer.buf = lpPerIOData->szMessage; lpPerIOData->sClient = g_sNewClientConnection; ret= WSARecv(lpPerIOData->sClient,//客户socket &lpPerIOData->Buffer, //存放接收数据的 1, //dwBufferCount [in] Number of WSABUF structures in the lpBuffers array. &lpPerIOData->NumberOfBytesRecvd,//存放接收数据的字节数 &lpPerIOData->Flags, &lpPerIOData->overlap, CompletionROUTINE); //如果接收的数据超过MSGSIZE 系统就会多次调用CompletionROUTINE,直到接收完.. printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); }}