在一个完成端口中,投递一次,怎么会返回多次,见内

lrj2005 2010-05-20 10:21:55
如下代码,我只投递了一个recv和一个send,怎么GetQueuedCompletionStatus总是一直能返回(应该我投递了一次,只返回一次啊),请教一下各位,帮忙看看问题出在哪了,谢谢。这是网上的一段代码,我实践时碰到的问题
服务器端:

#define PORT 5150
#define DATA_BUFSZIE 8192


// 单IO操作数据
typedef struct
{
OVERLAPPED oVerlapped;
WSABUF DATABuf;
CHAR Buffer[DATA_BUFSZIE];
DWORD BytesSend, BytesRecv;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;

// 单句柄操作数据
typedef struct
{
SOCKET Socket;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;

// 工作线程
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);



int _tmain(int argc, _TCHAR* argv[])
{
SOCKET localSockListen, acceptSocket;
WSADATA wsadata;
HANDLE completionPort;
SYSTEM_INFO systemInfo;
LPPER_HANDLE_DATA perHandleData;
LPPER_IO_OPERATION_DATA perIoData;
DWORD recvBytes;
DWORD flags;
DWORD threadID;
DWORD ret;

ret = WSAStartup(0x0202, &wsadata);
if (ret != 0)
{
printf("WSAStartup failed with error %d\n", ret);
}

completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (completionPort == NULL)
{
printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
}

GetSystemInfo(&systemInfo);

// 创建完成端口工作线程
for (int i=0; i < systemInfo.dwNumberOfProcessors; i++)
{
HANDLE threadHandle;
threadHandle = CreateThread(NULL, 0, ServerWorkerThread, completionPort, 0, &threadID);

if (threadHandle == NULL)
{
printf("CreateThread failed with error %d\n", GetLastError());
return 0;
}

CloseHandle(threadHandle);
}

// 创建监听端口
localSockListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if (localSockListen == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return 0;
}

SOCKADDR_IN localAddr;
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(PORT);

// 绑定Socket
ret = bind(localSockListen, (LPSOCKADDR)&localAddr, sizeof(SOCKADDR_IN));
if (ret == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return 0;
}

// 启动监听
if (listen(localSockListen, 10000) == SOCKET_ERROR)
{
printf("listen() failed with error %d\n", WSAGetLastError());
return 0;
}


// 接收连接请
while (TRUE)
{

acceptSocket = WSAAccept(localSockListen, NULL, NULL, NULL, 0);
if (acceptSocket == SOCKET_ERROR)
{
printf("WSAAccept() failed with error %d\n", WSAGetLastError());
return 0;
}

// 创建单句柄数据
perHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(perHandleData));
if (perHandleData == NULL)
{
printf("GlobalAlloc() failed with error %d\n", WSAGetLastError());
return 0;
}

printf("Socket Number %d\n", acceptSocket);
perHandleData->Socket = acceptSocket;

if(CreateIoCompletionPort((HANDLE)acceptSocket, completionPort, (DWORD)perHandleData, 0) == NULL)
{
printf("CreateIoCompletionPort() failed with error %d\n", WSAGetLastError());
return 0;
}

// 创建单IO数据
perIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));
if (perIoData == NULL)
{
printf("GlobalAlloc() failed with error %d\n", WSAGetLastError());
return 0;
}

ZeroMemory(&(perIoData->oVerlapped), sizeof(OVERLAPPED));

perIoData->DATABuf.buf = perIoData->Buffer;
perIoData->DATABuf.len = DATA_BUFSZIE;
perIoData->BytesRecv = 0;
perIoData->BytesSend = 0;
flags = 0;

if (WSARecv(acceptSocket, &(perIoData->DATABuf), 1, &recvBytes, &flags, &(perIoData->oVerlapped), NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSARecv() failed with error %d\n", WSAGetLastError());
return 0;
}
}
}

return 0;
}


DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE completionPort = (HANDLE)CompletionPortID;
DWORD BytesTransfer;
LPPER_HANDLE_DATA perHandleData;
LPPER_IO_OPERATION_DATA perIoData;
LPOVERLAPPED overLapped;
DWORD sendBytes, recvBytes;
DWORD flags;


while (TRUE)
{
if (GetQueuedCompletionStatus(completionPort, &BytesTransfer, (LPDWORD)&perHandleData, (LPOVERLAPPED*)&perIoData, INFINITE) == 0)
{
printf("GetQueuedCompletionStatus() failed with error %d\n", GetLastError());
return 0;
}

if (BytesTransfer == 0)
{
printf("closing socket %d\n", perHandleData->Socket);
if (closesocket(perHandleData->Socket) == SOCKET_ERROR)
{
printf("closesocket() failed with error %d\n", WSAGetLastError());
return 0;
}

GlobalFree(perHandleData);
GlobalFree(perIoData);

continue;
}

if (perIoData->BytesRecv == 0)
{
perIoData->BytesRecv = BytesTransfer;
perIoData->BytesSend = 0;
}
else
{
perIoData->BytesRecv += BytesTransfer;
}

BytesTransfer = 0;

if (perIoData->BytesRecv > perIoData->BytesSend)
{
ZeroMemory(&(perIoData->oVerlapped), sizeof(OVERLAPPED));
perIoData->DATABuf.buf = perIoData->Buffer + perIoData->BytesSend;
perIoData->DATABuf.len = perIoData->BytesRecv - perIoData->BytesSend;
flags = 0;

if (WSASend(perHandleData->Socket, &perIoData->DATABuf, 1, &sendBytes, 0, &perIoData->oVerlapped, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
}
}
else
{
perIoData->BytesRecv = 0;

ZeroMemory(&(perIoData->oVerlapped), sizeof(OVERLAPPED));
perIoData->DATABuf.buf = perIoData->Buffer;
perIoData->DATABuf.len = DATA_BUFSZIE;
flags = 0;

if (WSARecv(perHandleData->Socket, &perIoData->DATABuf, 1, &recvBytes, &flags, &perIoData->oVerlapped, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
return 0;
}
}
}

}

}


客户端

WSADATA wsadata;
SOCKET serverSocket;
SOCKADDR_IN serverAddr;
DWORD sendBytes, recvBytes;
CHAR buffer[DATA_BUFSIZE] = "hello, server !";


if (WSAStartup(0x0202, &wsadata) != 0)
{
printf("WSAStartup failed with error %d\n", WSAGetLastError());
return 0;
}

serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (serverSocket == INVALID_SOCKET)
{
printf("create socket failed with error %d\n", GetLastError());
return 0;
}

serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
serverAddr.sin_port = htons(PORT);

if (connect(serverSocket, (SOCKADDR*)&serverAddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
printf("connect() failed with error %d\n", WSAGetLastError());
return 0;
}

printf("connection successful! server Port : %d\n", serverSocket);

sendBytes = send(serverSocket, buffer, strlen(buffer)+1, 0);
printf("send bytes: %d\n", sendBytes);
memset(buffer, 0, DATA_BUFSIZE);
recvBytes = recv(serverSocket, buffer, DATA_BUFSIZE, 0);
printf("recv bytes: %d\n", recvBytes);
printf("recv Message: %s\n", buffer);
...全文
76 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
hsLi001 2010-05-21
  • 打赏
  • 举报
回复
我是来接分的。。。。。。。
lrj2005 2010-05-21
  • 打赏
  • 举报
回复
自己解决了,汗。。。
lrj2005 2010-05-21
  • 打赏
  • 举报
回复
怎么没人知道啊,晕
lrj2005 2010-05-20
  • 打赏
  • 举报
回复
没人啊。。。。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧