完成端口问题!使用AcceptEx后过一段时间(时间不定)就无法获得连接信息了!

Hxy129 2005-12-17 12:16:41
投递连接事件

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

PerIoData->OperationType = ACCP_POST;
PerIoData->AcceptSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, SA_FLAG_OVERLAPPED);

BOOL bReuseaddr = TRUE;

setsockopt(PerIoData->AcceptSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &bReuseaddr, sizeof(BOOL));

DWORD dwBytes;

BOOL rc = lpfnAcceptEx(Listen,
PerIoData->AcceptSocket,
PerIoData->Buffer,
0,
sizeof(SOCKADDR_IN) + 16,
sizeof(SOCKADDR_IN) + 16,
&dwBytes,
&(PerIoData->Overlapped));

完成端口查询到接收事件有信号的处理

// 获得连接信息

lpfnGetAcceptExSockAddrs(PerIoData->Buffer,
0,
sizeof(SOCKADDR_IN) + 16,
sizeof(SOCKADDR_IN) + 16,
(SOCKADDR **)(&lpLocalSockAddr),
&nLocalSockAddr,
(SOCKADDR **)(&lpRemoteSockAddr),
&nRemoteSockAddr);

// 终端设备关联完成端口
//

PerTerminalHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));
PerTerminalHandleData->Socket = PerIoData->AcceptSocket;
memcpy(&PerTerminalHandleData->ClientAddr, lpRemoteSockAddr, sizeof(SOCKADDR_IN));

CreateIoCompletionPort((HANDLE) PerTerminalHandleData->Socket,
hCompletionPort,
(DWORD) PerTerminalHandleData,
0);

// 投递一个接收事件
//

LPPER_IO_OPERATION_DATA PerTerminalIoData;
PerTerminalIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA));

PostRecv(PerTerminalHandleData->Socket, PerTerminalIoData);

// 投递一个Accept事件
//

PostAccept(PerHandleData->Socket, PerIoData);

一共开了两个工作器线程。运行一段时间就无法获得客户端连接了,从运行到出现问题这个时间
不太固定(不知道有什么规律),有时十分钟,有时好几个小时。其实客户端连接还是可以成功的,
就是完成端口获得不了连接的信息,好像是事件没有被指定为有信号。
...全文
306 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
fine10000 2005-12-19
  • 打赏
  • 举报
回复
学习ing
Hxy129 2005-12-19
  • 打赏
  • 举报
回复
高手都不在?

客户端连接成功说明监听socket还在工作,只是完成端口无法获得连接事件!

用AcceptEx获得客户端连接信息后马上在这个连接socket上投递一个WSARecv事件有时候
会失败,错误代码为10038,这是怎么回事?
freemme 2005-12-17
  • 打赏
  • 举报
回复
顶一下
IOCP全称I/O Completion Port,中文译为I/O完成端口。IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方法不同的是,一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端口就将被操作系统加入一个队列中。然后应用程序可以对核心层进行查询以得到此完成端口。 大体上来讲,使用完成端口只用遵循如下几个步骤: (1) 调用 CreateIoCompletionPort() 函数创建一个完成端口,而且在一般情况下,我们需要且只需要建立这一个完成端口,把它的句柄保存好,我们今后会经常用到它…… (2) 根据系统中有多少个处理器,就建立多少个工作者(为了醒目起见,下面直接说Worker)线程,这几个线程是专门用来和客户端进行通信的,目前暂时没什么工作; (3) 下面就是接收连入的Socket连接了,这里有两种实现方式:一是和别的编程模型一样,还需要启动一个独立的线程,专门用来accept客户端的连接请求;二是用性能更高更好的异步AcceptEx()请求。 (4) 每当有客户端连入的时候,我们就还是得调用CreateIoCompletionPort()函数,这里却不是新建立完成端口了,而是把新连入的Socket(也就是前面所谓的设备句柄),与目前的完成端口绑定在一起。 至此,我们其实就已经完成完成端口的相关部署工作了,嗯,是的,完事了,后面的代码里我们就可以充分享受完成端口带给我们的巨大优势,坐享其成了,是不是很简单呢? (5) 例如,客户端连入之后,我们可以在这个Socket上提交一个网络请求,例如WSARecv(),然后系统就会帮咱们乖乖的去执行接收数据的操作,我们大可以放心的去干别的事情了; (6) 而此时,我们预先准备的那几个Worker线程就不能闲着了, 我们在前面建立的几个Worker就要忙活起来了,都需要分别调用GetQueuedCompletionStatus() 函数在扫描完成端口的队列里是否有网络通信的请求存在(例如读取数据,发送数据等),一旦有的话,就将这个请求从完成端口的队列中取回来,继续执行本线程中后面的处理代码,处理完毕之后,我们再继续投递下一个网络通信的请求就OK了,如此循环。

18,356

社区成员

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

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