初学重叠I/O就遇到这样的问题;弄了好几天也不明白是怎么回事?
整个代码如下,然后通过客户端给该服务器端发送字符串,发送字符串第一次成功!发送字符串第二次成功!发送第三次的时候就收不到了;
运行过程同时发现WSAGetOverlappedResult()函数返回值是10014;
也不知道哪里出了问题?请大侠们给予测试或者指点;#include "stdafx.h"
#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 5150
#define MSGSIZE 1024
typedef struct
{
WSAOVERLAPPED overlap;
WSABUF Buffer;
char szMessage[MSGSIZE];
DWORD NumberOfBytesRecvd;
DWORD Flags;
} PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
int g_iTotalConn = 0;
SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
LPPER_IO_OPERATION_DATA g_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS];
DWORD WINAPI WorkerThread(LPVOID lpParam);
void Cleanup(int index);int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET sListen, sClient;
SOCKADDR_IN local, client;
DWORD dwThreadId;
int iAddrSize = sizeof(SOCKADDR_IN);
// Initialize windows socket library
WSAStartup(0x0202, &wsaData);
// Create listening socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind
local.sin_family = AF_INET;
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_port = htons(PORT);
bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
// Listen
listen(sListen, 3);
// Create worker thread
CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
while (TRUE)
{
// Accept a connection
sClient = accept(sListen, (struct sockaddr *)&client, &iAddrSize);
printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
g_CliSocketArr[g_iTotalConn] = sClient;
// Associate a PER_IO_OPERATION_DATA structure
g_pPerIoDataArr[g_iTotalConn] = (LPPER_IO_OPERATION_DATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PER_IO_OPERATION_DATA)); g_pPerIoDataArr[g_iTotalConn]->Flags=0;
g_pPerIoDataArr[g_iTotalConn]->Buffer.len = MSGSIZE;
g_pPerIoDataArr[g_iTotalConn]->Buffer.buf = g_pPerIoDataArr[g_iTotalConn]->szMessage;
g_CliEventArr[g_iTotalConn] = g_pPerIoDataArr[g_iTotalConn]->overlap.hEvent = WSACreateEvent();
// Launch an asynchronous operation
WSARecv(g_CliSocketArr[g_iTotalConn],
&g_pPerIoDataArr[g_iTotalConn]->Buffer,
1,
&g_pPerIoDataArr[g_iTotalConn]->NumberOfBytesRecvd,
&g_pPerIoDataArr[g_iTotalConn]->Flags,
&g_pPerIoDataArr[g_iTotalConn]->overlap,
NULL);
g_iTotalConn++;
}
closesocket(sListen);
WSACleanup();
return 0;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
//unsigned char first[128]={0};
int ret, index;
BOOL bResult = TRUE;
DWORD returnValue;
DWORD cbTransferred; char buffBack[3]="abc";
DWORD dwBytes=0,dwFlags=0;
WSABUF DataBuf;
//ZeroMemory(&wsaBuf,sizeof(WSABUF));
DataBuf.len=3;
DataBuf.buf=buffBack;
while (TRUE)
{
ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
}
index = ret - WSA_WAIT_EVENT_0;
bResult =WSAResetEvent(g_CliEventArr[index]);
if (bResult == FALSE) {
wprintf(L"WSAResetEvent failed with error = %d\n", WSAGetLastError());
}
bResult =WSAGetOverlappedResult(g_CliSocketArr[index],
&g_pPerIoDataArr[index]->overlap,
&cbTransferred,
TRUE,
&g_pPerIoDataArr[g_iTotalConn]->Flags);
if (bResult == FALSE) {
wprintf(L"WSAGetOverlappedResult failed with error = %d\n", WSAGetLastError());
}
if (cbTransferred == 0)
{
// The connection was closed by client
Cleanup(index);
}
else
{
WSARecv(g_CliSocketArr[index],
&g_pPerIoDataArr[index]->Buffer,
1,
&g_pPerIoDataArr[index]->NumberOfBytesRecvd,
&g_pPerIoDataArr[index]->Flags,
&g_pPerIoDataArr[index]->overlap,
NULL);
memset(&(g_pPerIoDataArr[index]->overlap), '\0', sizeof(WSAOVERLAPPED));//将overlapped结构清空
returnValue=WSASend(g_CliSocketArr[index], &DataBuf, 1, &dwBytes, dwFlags, &g_pPerIoDataArr[index]->overlap, NULL);
printf("%s",g_pPerIoDataArr[index]->Buffer.buf);
}
}
return 0;
}
void Cleanup(int index)
{
closesocket(g_CliSocketArr[index]);
WSACloseEvent(g_CliEventArr[index]);
HeapFree(GetProcessHeap(), 0, g_pPerIoDataArr[index]);
if (index < g_iTotalConn-1)
{
g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn-1];
g_CliEventArr[index] = g_CliEventArr[g_iTotalConn-1];
g_pPerIoDataArr[index] = g_pPerIoDataArr[g_iTotalConn-1];
}
g_pPerIoDataArr[--g_iTotalConn] = NULL;
}
整个代码如下,然后通过客户端给该服务器端发送字符串,发送字符串第一次成功!发送字符串第二次成功!发送第三次的时候就收不到了;
运行过程同时发现WSAGetOverlappedResult()函数返回值是10014;
也不知道哪里出了问题?请大侠们给予测试或者指点;#include "stdafx.h"
#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 5150
#define MSGSIZE 1024
typedef struct
{
WSAOVERLAPPED overlap;
WSABUF Buffer;
char szMessage[MSGSIZE];
DWORD NumberOfBytesRecvd;
DWORD Flags;
} PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
int g_iTotalConn = 0;
SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
LPPER_IO_OPERATION_DATA g_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS];
DWORD WINAPI WorkerThread(LPVOID lpParam);
void Cleanup(int index);int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET sListen, sClient;
SOCKADDR_IN local, client;
DWORD dwThreadId;
int iAddrSize = sizeof(SOCKADDR_IN);
// Initialize windows socket library
WSAStartup(0x0202, &wsaData);
// Create listening socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Bind
local.sin_family = AF_INET;
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_port = htons(PORT);
bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
// Listen
listen(sListen, 3);
// Create worker thread
CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
while (TRUE)
{
// Accept a connection
sClient = accept(sListen, (struct sockaddr *)&client, &iAddrSize);
printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
g_CliSocketArr[g_iTotalConn] = sClient;
// Associate a PER_IO_OPERATION_DATA structure
g_pPerIoDataArr[g_iTotalConn] = (LPPER_IO_OPERATION_DATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PER_IO_OPERATION_DATA)); g_pPerIoDataArr[g_iTotalConn]->Flags=0;
g_pPerIoDataArr[g_iTotalConn]->Buffer.len = MSGSIZE;
g_pPerIoDataArr[g_iTotalConn]->Buffer.buf = g_pPerIoDataArr[g_iTotalConn]->szMessage;
g_CliEventArr[g_iTotalConn] = g_pPerIoDataArr[g_iTotalConn]->overlap.hEvent = WSACreateEvent();
// Launch an asynchronous operation
WSARecv(g_CliSocketArr[g_iTotalConn],
&g_pPerIoDataArr[g_iTotalConn]->Buffer,
1,
&g_pPerIoDataArr[g_iTotalConn]->NumberOfBytesRecvd,
&g_pPerIoDataArr[g_iTotalConn]->Flags,
&g_pPerIoDataArr[g_iTotalConn]->overlap,
NULL);
g_iTotalConn++;
}
closesocket(sListen);
WSACleanup();
return 0;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
//unsigned char first[128]={0};
int ret, index;
BOOL bResult = TRUE;
DWORD returnValue;
DWORD cbTransferred; char buffBack[3]="abc";
DWORD dwBytes=0,dwFlags=0;
WSABUF DataBuf;
//ZeroMemory(&wsaBuf,sizeof(WSABUF));
DataBuf.len=3;
DataBuf.buf=buffBack;
while (TRUE)
{
ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
}
index = ret - WSA_WAIT_EVENT_0;
bResult =WSAResetEvent(g_CliEventArr[index]);
if (bResult == FALSE) {
wprintf(L"WSAResetEvent failed with error = %d\n", WSAGetLastError());
}
bResult =WSAGetOverlappedResult(g_CliSocketArr[index],
&g_pPerIoDataArr[index]->overlap,
&cbTransferred,
TRUE,
&g_pPerIoDataArr[g_iTotalConn]->Flags);
if (bResult == FALSE) {
wprintf(L"WSAGetOverlappedResult failed with error = %d\n", WSAGetLastError());
}
if (cbTransferred == 0)
{
// The connection was closed by client
Cleanup(index);
}
else
{
WSARecv(g_CliSocketArr[index],
&g_pPerIoDataArr[index]->Buffer,
1,
&g_pPerIoDataArr[index]->NumberOfBytesRecvd,
&g_pPerIoDataArr[index]->Flags,
&g_pPerIoDataArr[index]->overlap,
NULL);
memset(&(g_pPerIoDataArr[index]->overlap), '\0', sizeof(WSAOVERLAPPED));//将overlapped结构清空
returnValue=WSASend(g_CliSocketArr[index], &DataBuf, 1, &dwBytes, dwFlags, &g_pPerIoDataArr[index]->overlap, NULL);
printf("%s",g_pPerIoDataArr[index]->Buffer.buf);
}
}
return 0;
}
void Cleanup(int index)
{
closesocket(g_CliSocketArr[index]);
WSACloseEvent(g_CliEventArr[index]);
HeapFree(GetProcessHeap(), 0, g_pPerIoDataArr[index]);
if (index < g_iTotalConn-1)
{
g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn-1];
g_CliEventArr[index] = g_CliEventArr[g_iTotalConn-1];
g_pPerIoDataArr[index] = g_pPerIoDataArr[g_iTotalConn-1];
}
g_pPerIoDataArr[--g_iTotalConn] = NULL;
}
(10014-系统检测到在一个调用中尝试使用指针参数时的无效指针地址。 )
要等到IO完成后才能重用
并且要memset一下,但要注意那个hEvent成员不能置NULLWSARecv后立即又WSASend,用的是同一个overlap
而且memset(&(g_pPerIoDataArr[index]->overlap), '\0', sizeof(WSAOVERLAPPED));//将overlapped结构清空
这句把overlap.hEvent也置NULL了想有收发
可以再增加一线程,代码照搬recv的
或者将原来的全局变量修改下
如
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
LPPER_IO_OPERATION_DATA g_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS];
改成
WSAEVENT g_CliEventArr[2][MAXIMUM_WAIT_OBJECTS];
LPPER_IO_OPERATION_DATA g_pPerIoDataArr[2][MAXIMUM_WAIT_OBJECTS];
http://blog.csdn.net/visualeleven/article/details/5991743
for(int i = dwIndex; i < g_nIndex; i++)
{
dwIndex = WSAWaitForMultipleEvents(1, &g_event[dwIndex], TRUE, INFINITE, FALSE);
if(WSA_WAIT_FAILED == dwIndex)
{
continue;
} 你好;
其中WSAWaitForMultipleEvents()的第一个参数1在这里有何预意?
#include "stdafx.h"
#include <WINSOCK2.H>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#define PORT 2023
#define MSGSIZE 32
typedef enum _OPERATION_INFO
{
OP_NULL,
OP_READ,
OP_WRITE
}OPERATIONINFO;
typedef struct
{
WSAOVERLAPPED overlap;
WSABUF wsaBuf;
char szBuf[MSGSIZE];
DWORD NumberOfBytesRecvd;
DWORD Flags;
SOCKET sock;
SOCKADDR_IN addr;
OPERATIONINFO nOpType;
} PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;
int g_iTotalConn = 0;
SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS]={0};
LPPER_IO_OPERATION_DATA g_pPerIoDataArr[MAXIMUM_WAIT_OBJECTS]={0};
BOOL g_bExitThread = FALSE;
DWORD WINAPI WorkerThread(LPVOID lpParam);
void Cleanup(int index);
int main(int argc, char* argv[])
{
DWORD dwTrans = 0;
DWORD dwFlags = 0;
HANDLE hThread;
WSADATA wsaData;
SOCKET sListen, sClient;
SOCKADDR_IN local, client;
DWORD dwThreadId;
int iAddrSize = sizeof(SOCKADDR_IN);
if(0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
{
printf("WSAStartup failed with error code: %d/n", GetLastError());
return 0;
}
sListen = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if(INVALID_SOCKET == sListen)
{
printf("socket failed with error code: %d\n", WSAGetLastError());
WSACleanup();
return 0;
}
local.sin_family = AF_INET;
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_port = htons(PORT);
if(SOCKET_ERROR == bind(sListen, (LPSOCKADDR)&local, sizeof(local)))
{
printf("bind failed with error code: %d/n", WSAGetLastError());
closesocket(sListen);
sListen = INVALID_SOCKET;
WSACleanup();
return 0;
}
if(SOCKET_ERROR == listen(sListen, 5))
{
printf("listen failed with error code: %d\n", WSAGetLastError());
closesocket(sListen);
sListen = INVALID_SOCKET;
WSACleanup();
return 0;
}
hThread=CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId);
if(NULL == hThread)
{
printf("CreateThread failed with error code: %d\n", GetLastError());
closesocket(sListen);
sListen = INVALID_SOCKET;
WSACleanup();
return 0;
}
printf("Server start listen and wait for client to connect ...\n");
while (TRUE)
{
if(g_iTotalConn >= WSA_MAXIMUM_WAIT_EVENTS)
{
printf("Too many connect, wait for disconnect .../n");
continue;
}
sClient = accept(sListen, (struct sockaddr *)&client, &iAddrSize);
if(INVALID_SOCKET == sClient)
{
printf("accept failed with error code: %d\n", WSAGetLastError());
continue;
}
printf("<IP: %s, Port: %d> client come in.\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
g_pPerIoDataArr[g_iTotalConn] = (LPPER_IO_OPERATION_DATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PER_IO_OPERATION_DATA));
g_pPerIoDataArr[g_iTotalConn]->sock = sClient;
memcpy(&g_pPerIoDataArr[g_iTotalConn]->addr, &client, sizeof(client));
g_pPerIoDataArr[g_iTotalConn]->szBuf[0]=0;
g_pPerIoDataArr[g_iTotalConn]->wsaBuf.len = MSGSIZE;
g_pPerIoDataArr[g_iTotalConn]->wsaBuf.buf = g_pPerIoDataArr[g_iTotalConn]->szBuf;
g_CliEventArr[g_iTotalConn] = g_pPerIoDataArr[g_iTotalConn]->overlap.hEvent = WSACreateEvent();
g_pPerIoDataArr[g_iTotalConn]->nOpType = OP_READ;
if(SOCKET_ERROR == WSARecv(g_pPerIoDataArr[g_iTotalConn]->sock,
&(g_pPerIoDataArr[g_iTotalConn]->wsaBuf),
1, &dwTrans, &dwFlags,
(LPWSAOVERLAPPED)&(g_pPerIoDataArr[g_iTotalConn]->overlap),
NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSARecv failed with error code: %d\n", WSAGetLastError());
closesocket(g_pPerIoDataArr[g_iTotalConn]->sock);
HeapFree(GetProcessHeap(), 0, g_pPerIoDataArr g_pPerIoDataArr[g_iTotalConn] = NULL;
continue;
}
}
g_iTotalConn++;
}
g_bExitThread = TRUE;
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
closesocket(sListen);
WSACleanup();
return 0;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
DWORD dwIndex;
int i;
BOOL bRet;
DWORD dwTrans = 0;
char buffBack[3]="abc";
DWORD dwBytes=0,dwFlags=0;
DataBuf.len=3;
DataBuf.buf=buffBack;
while (!g_bExitThread)
{
dwIndex = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
if(WSA_WAIT_FAILED == dwIndex || WSA_WAIT_TIMEOUT == dwIndex)
{
continue;
}
dwIndex -= WSA_WAIT_EVENT_0;
for(i = dwIndex; i < g_iTotalConn; i++)
{
dwIndex = WSAWaitForMultipleEvents(1, &g_CliEventArr[dwIndex], TRUE, INFINITE, FALSE);
if(WSA_WAIT_FAILED == dwIndex)
{
continue;
}
dwIndex -= WSA_WAIT_EVENT_0;
WSAResetEvent(g_CliEventArr[dwIndex]);
bRet = WSAGetOverlappedResult(g_pPerIoDataArr[dwIndex]->sock, &(g_pPerIoDataArr[dwIndex]->overlap), &dwTrans, FALSE, &dwFlags);
if(bRet)
{
if(dwTrans > 0)
{
switch(g_pPerIoDataArr[dwIndex]->nOpType)
{
case OP_READ:
{
printf("recv client <%s:%d> data: %s\n", inet_ntoa(g_pPerIoDataArr[dwIndex]->addr.sin_addr), ntohs(g_pPerIoDataArr[dwIndex]->addr.sin_port), g_pPerIoDataArr[dwIndex]->szBuf);
g_pPerIoDataArr[dwIndex]->nOpType = OP_WRITE;
memset(&(g_pPerIoDataArr[dwIndex]->overlap), 0, sizeof(g_pPerIoDataArr[dwIndex]->overlap));
if(SOCKET_ERROR == WSASend(g_pPerIoDataArr[dwIndex]->sock, &(g_pPerIoDataArr[dwIndex]->wsaBuf), 1, &dwTrans, dwFlags, &(g_pPerIoDataArr[dwIndex]->overlap), NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSASend failed with error code: %d/n", WSAGetLastError());
continue;
}
}
}
break;
case OP_WRITE:
{
g_pPerIoDataArr[dwIndex]->nOpType = OP_READ;
memset(&(g_pPerIoDataArr[dwIndex]->overlap), 0, sizeof(g_pPerIoDataArr[dwIndex]->overlap));
memset(g_pPerIoDataArr[dwIndex]->szBuf, 0, sizeof(g_pPerIoDataArr[dwIndex]->szBuf));
dwFlags = 0;
g_pPerIoDataArr[dwIndex]->wsaBuf.buf = g_pPerIoDataArr[dwIndex]->szBuf;
dwTrans = g_pPerIoDataArr[dwIndex]->wsaBuf.len = MSGSIZE;
if(SOCKET_ERROR == WSARecv(g_pPerIoDataArr[dwIndex]->sock, &(g_pPerIoDataArr[dwIndex]->wsaBuf), 1, &dwTrans, &dwFlags, &(g_pPerIoDataArr[dwIndex]->overlap), NULL))
{
if(ERROR_IO_PENDING != WSAGetLastError())
{
printf("WSARecv failed with error code: %d/n", WSAGetLastError());
continue;
}
}
}
break;
default:
break; }
}
else
{
printf("client <%s : %d> leave.\n", inet_ntoa(g_pPerIoDataArr[dwIndex]->addr.sin_addr), ntohs(g_pPerIoDataArr[dwIndex]->addr.sin_port));
closesocket(g_pPerIoDataArr[dwIndex]->sock);
WSACloseEvent(g_CliEventArr[dwIndex]);
HeapFree(GetProcessHeap(), 0, g_pPerIoDataArr[g_iTotalConn]);
g_pPerIoDataArr[g_iTotalConn] = NULL;
for( i= dwIndex; i<g_iTotalConn-1; i++)
{
g_CliEventArr[i] = g_CliEventArr[i+1];
g_pPerIoDataArr[i] = g_pPerIoDataArr[i+1];
}
g_iTotalConn--;
}
}
else
{
printf("WSAGetOverlappedResult failed with error: %d\n", WSAGetLastError());
}
}
}
printf("Server to exit ... \n");
return 0;
}
第一次可以接收到字符串,第二次就无法接收到字符串;这是什么原因?
http://blog.csdn.net/visualeleven/article/details/5991743
这句把overlap.hEvent也置NULL了“
既然清空了,那我就重新:
g_pPerIoDataArr[Index]->overlap.hEvent = g_CliEventArr[Index];