GetQueuedCompletionStatus如何判断发送完毕还是接收完毕

数世纪 2008-10-26 11:39:04
GetQueuedCompletionStatus怎么判断是发送完毕还是接收完毕,我看上面主要是用结构PER_IO_OPERATION_DATA,里面第一个数据是OVERLAPPED类型,怎样再加一个数据?可以标示状态。
谢谢
#include <winsock2.h >
#include < windows.h >
#include < stdio.h >
#define PORT 5150
#define DATA_BUFSIZE 8192
// 关键项
typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DATA_BUFSIZE];
DWORD BytesSEND;
DWORD BytesRECV;
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;


typedef struct
{
SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);

void main( void )
{
SOCKADDR_IN InternetAddr;
SOCKET Listen;
SOCKET Accept;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
int i;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;

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

// 打开一个空的完成端口

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

// Determine how many processors are on the system.

GetSystemInfo( & SystemInfo);

// 开启cpu个数的2倍个的线程

for (i = 0 ; i < SystemInfo.dwNumberOfProcessors * 2 ; i ++ )
{
HANDLE ThreadHandle;

// Create a server worker thread and pass the completion port to the thread.

if ((ThreadHandle = CreateThread(NULL, 0 , ServerWorkerThread, CompletionPort,
0 , & ThreadID)) == NULL)
{
printf( " CreateThread() failed with error %d\n " , GetLastError());
return ;
}

// Close the thread handle
CloseHandle(ThreadHandle);
}

// 打开一个服务器socket

if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0 , NULL, 0 ,
WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
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(PORT);

if (bind(Listen, (PSOCKADDR) & InternetAddr, sizeof (InternetAddr)) == SOCKET_ERROR)
{
printf( " bind() failed with error %d\n " , WSAGetLastError());
return ;
}


if (listen(Listen, 5 ) == SOCKET_ERROR)
{
printf( " listen() failed with error %d\n " , WSAGetLastError());
return ;
}

// 开始接收从客户端来的连接
printf("begin to get link request \n");
while (TRUE)
{
if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0 )) == SOCKET_ERROR)
{
printf( " WSAAccept() failed with error %d\n " , WSAGetLastError());
return ;
}

// 创建一个关键项用于保存这个客户端的信息,用户接收发送的重叠结构,
// 还有使用到的缓冲区
if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR,
sizeof (PER_HANDLE_DATA))) == NULL)
{
printf( " GlobalAlloc() failed with error %d\n " , GetLastError());
return ;
}

// Associate the accepted socket with the original completion port.

printf( " Socket number %d connected\n " , Accept);
PerHandleData -> Socket = Accept;

// 与我们的创建的那个完成端口关联起来,将关键项也与指定的一个完成端口关联
if (CreateIoCompletionPort((HANDLE) Accept, CompletionPort, (DWORD) PerHandleData,
0 ) == NULL)
{
printf( " CreateIoCompletionPort failed with error %d\n " , GetLastError());
return ;
}

// 投递一次接收,由于接收都需要使用这个函数来投递一个接收的准备

if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof (PER_IO_OPERATION_DATA))) == NULL)
{
printf( " GlobalAlloc() failed with error %d\n " , GetLastError());
return ;
}

ZeroMemory( & (PerIoData -> Overlapped), sizeof (OVERLAPPED));
PerIoData -> BytesSEND = 0 ;
PerIoData -> BytesRECV = 0 ;
PerIoData -> DataBuf.len = DATA_BUFSIZE;
PerIoData -> DataBuf.buf = PerIoData -> Buffer;

Flags = 0 ;
if (WSARecv(Accept, & (PerIoData -> DataBuf), 1 , & RecvBytes, & Flags,
& (PerIoData -> Overlapped), NULL) == SOCKET_ERROR)
{
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_HANDLE_DATA PerHandleData;
LPPER_IO_OPERATION_DATA PerIoData;
DWORD SendBytes, RecvBytes;
DWORD Flags;
printf("enter the work thread \n");
while (TRUE)
{
// 完成端口有消息来了
if (GetQueuedCompletionStatus(CompletionPort, & BytesTransferred,
(LPDWORD) & PerHandleData, (LPOVERLAPPED * ) & PerIoData, INFINITE) == 0 )
{
printf( " GetQueuedCompletionStatus failed with error %d\n " , GetLastError());
return 0 ;
}
///*add 问题:怎么在这里判断是发送完消息还是接收完消息
else
{
//printf("%d",int(& PerHandleData));
printf(PerIoData->Buffer);
printf("22222\n");
}
//*/end add

// 是不是有人退出了

if (BytesTransferred == 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 = BytesTransferred;
PerIoData -> BytesSEND = 0 ;
}
else
{
PerIoData -> BytesSEND += BytesTransferred;
}
if (PerIoData -> BytesRECV > PerIoData -> BytesSEND)
{

ZeroMemory( & (PerIoData -> Overlapped), sizeof (OVERLAPPED));

PerIoData -> DataBuf.buf = PerIoData -> Buffer + PerIoData -> BytesSEND;
PerIoData -> DataBuf.len = PerIoData -> BytesRECV - PerIoData -> BytesSEND;

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 ;

// Now that there are no more bytes to send post another WSARecv() request.

Flags = 0 ;
ZeroMemory( & (PerIoData -> Overlapped), sizeof (OVERLAPPED));

PerIoData -> DataBuf.len = DATA_BUFSIZE;
PerIoData -> DataBuf.buf = PerIoData -> Buffer;

if (WSARecv(PerHandleData -> Socket, & (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 ;
}
}
}
}
}
...全文
172 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
数世纪 2008-10-26
  • 打赏
  • 举报
回复
或者说,每次发送和接收都自己新建一个PER_IO_OPERATION_DATA类型的数据,然后自己填充?说是发送还是接收。。?
数世纪 2008-10-26
  • 打赏
  • 举报
回复
问题我用中文标出来了,就在那个地方怎么判断,我看了windows网络编程,也没看明白
kevin0808 2008-10-26
  • 打赏
  • 举报
回复
你这段程序是通过控制交叠结构中的 DWORD BytesSEND; DWORD BytesRECV; 两个量来判断是发送完毕还是接受完毕的,不过我不喜欢这种方法
我建议的方法是在交叠结构中定一个变量,就定义int type;好了,调用send前,我就将type=1,调用recv前,我就将type=2,那么在GetQueuedCompletionStatus到完成事件后,我取出交接结构,看type的值,是1的话,表明是发送完成,2的话是接收完成
数世纪 2008-10-26
  • 打赏
  • 举报
回复
看了别人写的几个程序。。。应该就是 。。。自己填充。。。

18,356

社区成员

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

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