当我需要关闭一个端口时,调用了CancelIO,然后再使用shutdown和closesocket,理论上在此端口的所有pending中的IO操作都会被取消掉。
但为何我原先投递的WSARecv的操作有时候还是会接收到IO完成消息,接收到字节数为○,或者有时候GetQueuedCompliationStatus返回一个错误码,错误码是995或者10038之类的。(995是ABORT可以理解的,但为何只是有时候收到,而不是每次收到?)此外还有问题就是:
一。如何确定我需要投递的acceptex请求?投递多了,浪费资源,投递少了又会引起连接拒绝?有没有函数可以知道listen中指定的那个backlog参数,已经被用掉几个了?二。WSARecv中的缓冲区大小是固定的,也就是说接收满缓冲以后才返回,那如果客户端每次发送包的大小不一样怎么办?我现在是在每个包头加一个4字节大小的包头,每次先收4字节,然后再根据收到的大小来确定WSABUF中缓冲区的大小。有没有更好的方法可以解决?thanks
但为何我原先投递的WSARecv的操作有时候还是会接收到IO完成消息,接收到字节数为○,或者有时候GetQueuedCompliationStatus返回一个错误码,错误码是995或者10038之类的。(995是ABORT可以理解的,但为何只是有时候收到,而不是每次收到?)此外还有问题就是:
一。如何确定我需要投递的acceptex请求?投递多了,浪费资源,投递少了又会引起连接拒绝?有没有函数可以知道listen中指定的那个backlog参数,已经被用掉几个了?二。WSARecv中的缓冲区大小是固定的,也就是说接收满缓冲以后才返回,那如果客户端每次发送包的大小不一样怎么办?我现在是在每个包头加一个4字节大小的包头,每次先收4字节,然后再根据收到的大小来确定WSABUF中缓冲区的大小。有没有更好的方法可以解决?thanks
解决方案 »
- CImage显示略缩图时有问题。
- 给点指导吧
- 给个注意,谢谢
- 怎么用代码控制CFormView中的的IDD_DIALOG的大小??高分!!急!!
- MFC调用SQL语句,在线等啊
- CreateFile()這個API函數的參數問題.
- 关于自定义类的问题
- 请问 : ocx组件 放在服务器端并注册成功,网页调用ocx也成功(服务器端),把调用成功的网页发布,但是通过客户端网页调用服务器网页,提示无法识别ocx组件
- 想在listctrl中加入一个树型结构,使点击+后,目录(列表的项目)可以显示相应的文件名
- 一定有人知道!
- 如何在文件中从末尾查找字符串,返回第一次找到的位置???在线!!!!!!!!!!
- 我开了一个新的FTP,希望大家支持,谢谢!~
其中SI是每次投递的IO请求的buffer地址,不同的SI就代表着不同的socket 连接(在投递AcceptEx时生成的),这里有3个不同的连接A,B,C(虽然socket句柄是一样的,但也应该是不同的连接)
A:
current Event:close_socket SI:0xd6f1b8 SOCKET:2740 bytes:0
Cancel socket operator:2740 --->>>调用了CancelIO函数
Close a socket 2740 --->>>调用closesocket关闭2740current Event:recv SI:0xd6f1b8 SOCKET:2740 bytes:4 -->CancelIO没有起作用?
receive a packet head SI:0xd6f1b8 SOCKET:2740 bytes:4......................... -->省略了很多无关log记录
.........................
B:
current Event:close_socket SI:0xd68e40 SOCKET:2740 bytes:0
Cancel socket operator:2740 --->>>调用了CancelIO函数
Close a socket 2740 --->>>2740被关闭了C:
current Event:accept_connection SI:0xd83270 SOCKET:2816 bytes:0
Generate a new SI:0xd71e40 when ACCEPT SOCKET:2740 --->>>>>2740被重新分配给AcceptEx,并投递了一个IO请求current Event:close_socket SI:0xd63388 SOCKET:2876 bytes:0
Cancel socket operator:2876
Close a socket 2876
current Event:close_socket SI:0xd68d88 SOCKET:2724 bytes:0
Cancel socket operator:2724
Close a socket 2724
current Event:recv SI:0xd82600 SOCKET:2780 bytes:4
receive a packet head SI:0xd82600 socket:2780
current Event:recv SI:0xd75430 SOCKET:2824 bytes:4
receive a packet head SI:0xd75430 socket:2824
WSARecv() 3 failed with error 10038
current Event:accept_connection SI:0xd93f60 SOCKET:2736 bytes:0
Generate a new SI:0xda4418 when ACCEPT SOCKET:2724
current Event:recv SI:0xd8c420 SOCKET:2760 bytes:4
receive a packet head SI:0xd8c420 socket:2760
WSARecv() 3 failed with error 10038
current Event:2 SI:0xd68d88 SOCKET:2724 bytes:4
receive a packet head SI:0xd68d88 socket:2724current Event:recv SI:0xd6f1b8 SOCKET:2740 bytes:4 -->>>注意SI地址,竟然收到了很早就被我closesocket掉的A处socket投递的IO请求current Event:recv SI:0xd68e40 SOCKET:2740 bytes:4 -->>>收到了已经关闭的B处socket的IO
_________
注册 FD_ACCEPT 消息. 如果你没有ACCEPTEX可用了, 那么有新的连接请求时,你就会收到这个消息. 二。WSARecv中的缓冲区大小是固定的,也就是说接收满缓冲以后才返回,那如果客户端每次发送包的大小不一样怎么办?我现在是在每个包头加一个4字节大小的包头,每次先收4字节,然后再根据收到的大小来确定WSABUF中缓冲区的大小。有没有更好的方法可以解决?thanks
___________
不是啊, 客户端发送一段数据, WSARECV收到了就会返回, 不是一定要填满了才返回. 当底层TCP的接收缓冲区中已经没有数据可以复制到 WSARECV 提供的BUFFER中时,WSARECV就会返回.
对于第二个问题。我陈述错了(被这个麻烦的东西搞晕掉了)。当这个问题不存在好了。呵呵 sorry关键在于第一个问题,不管有没有CancelIo的调用,closesocket都会引起一个pending的操作完成。当你需要关闭端口时, 只需要调用 closesocket 即可,所有PENDING的WSARECV操作都会立即完成. 不需要 CancelIO.
-----------------------
意思是所有投递了的IO操作会被GetQueuedCompleteStatus立即弹出,还是指不会被弹出了?
________
会弹出呀,比如 WSARecv 正常返回, 字节数为0. 或者返回一个出错的值.
我的意思是用 WSAEventSelect(... FD_ACCEPT ) + 独立的线程来 WaitForSingleObject .
会弹出呀,比如 WSARecv 正常返回, 字节数为0. 或者返回一个出错的值.-----------------
不知是不是我理解错了
WSARecv在调用closesocket后是会返回出错或者0字节,但我关注的是已经使用WSARecv投递了的IO请求。
在closesocket之前对于GetQueuedCompleteStatus的调用是阻塞在那里的,
当调用closesocket时GetQueuedCompleteStatus对于此socket会不会立即返回呢?或者GetQueuedCompleteStatus是不会再返回此socket已投递的任何IO信息。
对于你的回答,我非常感谢。
___________
会立即返回呀,返回的就是 WSARECV 的这个IO操作, 表示 WSARECV 操作完成.
1.WSARecv(s) -->>返回IO_PENDING IO操作投递成功
2.WSARecv(s) -->>返回IO_PENDING IO操作投递成功
3.closesocket(s) 关闭socket
4.GetQueuedCompleteStatus()那第4步是得到前面两个投递成功了的IO操作呢,还是返回两个WSA_IO_ABORT。或者是阻塞在那里,什么都不返回?