IOCP模型 客户端断线问题

ahniyilin 2009-11-24 07:27:42
服务器端使用IOCP模型,在接收客户端请求后,服务器端会不停的发送数据给客户端。

当客户端短线时候,GetQueuedCompletionStatus可以接收到返回值false,判断客户端断线,然后停止发送数据。

但在客户端断线开始和服务器停止发送期间,肯定会投递很多send请求的。

而GetQueuedCompletionStatus只会在断线那一次才会返回false,对于后续的send请求操作失败则没有反应的。

我的做法是每次send的时候都会开辟一块内存区,在正常情况下GetQueuedCompletionStatus接收返回值的时候,释放内存

区。对于断线情况,我选择在send失败的时候,释放内存区。

问题一:我这样做有问题没?有没有更好的解决办法?

问题二:send的时候,在断线的那一次是发送的结果是返回成功呢还是返回失败呢?我感觉是算send成功。如果是返回失败的

话,我在send的时候释放内存,在GetQueuedCompletionStatus的时候也释放内存,不就2次释放了?

欢迎大家来讨论


...全文
247 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
ahniyilin 2009-11-25
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 makui 的回复:]
引用 8 楼 ahniyilin 的回复:

第二次发送还要等第一次是否发送完成,这样判断的话,还有必要用IOCP吗?
投递多个send的时候,目的就是为了快,专一做事情,这本身没有错的!
我提的问题是发生状况时侯才出现的问题?


快要建立在什么的其础上?正确都不能保证你发得再快有什么用?
在数据发送频率高的时候,不能发完的情况经常会出现。

都不太想回了,你怎么用这种口气!
[/Quote]
我想你还是没有看明白我想问的问题吧?!
makui 2009-11-25
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 ahniyilin 的回复:]

第二次发送还要等第一次是否发送完成,这样判断的话,还有必要用IOCP吗?
投递多个send的时候,目的就是为了快,专一做事情,这本身没有错的!
我提的问题是发生状况时侯才出现的问题?
[/Quote]

快要建立在什么的其础上?正确都不能保证你发得再快有什么用?
在数据发送频率高的时候,不能发完的情况经常会出现。

都不太想回了,你怎么用这种口气!
ahniyilin 2009-11-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 makui 的回复:]
你不应该投递多个WSASend请求。
原因在于:并不是每一次WSASend调用都能把WSABuf中的数据发完,即有可能你要发送100字节,结果只成了发送了50字节,整个数据流就全部乱掉了。
正确的做法应该是:为每一个客户端建立一下发送缓冲区列队,当你要发送数据的时候,首先应该看上一次WSASend调用是否完成,如果还没有安成则把数据放入缓冲区里面。
当每一次WSASend接到完成通知后:
首先要判断本次传输成功的字节数与你投递的WSABuf的长度是否一致,如果不一致那就应该构造下一次WSASend,将剩下的数据发送出去。
否则你查看跟本客户端相对应的缓冲队列里面是否还有未完成的数据,如果有,从缓冲区里取出一份构造WSASend请求。。。

表达不是很专业,后面的看不明白不要紧(是解决方法之一),但是第一句所述的事实你应该要明白

[/Quote]

第二次发送还要等第一次是否发送完成,这样判断的话,还有必要用IOCP吗?
投递多个send的时候,目的就是为了快,专一做事情,这本身没有错的!
我提的问题是发生状况时侯才出现的问题?
makui 2009-11-25
  • 打赏
  • 举报
回复
你不应该投递多个WSASend请求。
原因在于:并不是每一次WSASend调用都能把WSABuf中的数据发完,即有可能你要发送100字节,结果只成了发送了50字节,整个数据流就全部乱掉了。
正确的做法应该是:为每一个客户端建立一下发送缓冲区列队,当你要发送数据的时候,首先应该看上一次WSASend调用是否完成,如果还没有安成则把数据放入缓冲区里面。
当每一次WSASend接到完成通知后:
首先要判断本次传输成功的字节数与你投递的WSABuf的长度是否一致,如果不一致那就应该构造下一次WSASend,将剩下的数据发送出去。
否则你查看跟本客户端相对应的缓冲队列里面是否还有未完成的数据,如果有,从缓冲区里取出一份构造WSASend请求。。。

表达不是很专业,后面的看不明白不要紧(是解决方法之一),但是第一句所述的事实你应该要明白
ahniyilin 2009-11-25
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 tech_study_00 的回复:]
GetQueuedCompletionStatus对于一个无效的已经关闭的句柄是无效的。
[/Quote]
我没有关闭,但是也没有反应的
ahniyilin 2009-11-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 myy 的回复:]
而GetQueuedCompletionStatus只会在断线那一次才会返回false,对于后续的send请求操作失败则没有反应的。

----

不是这样的,只要不关闭完成端口的句柄并且一直GetQueuedCompletionStatus,所有投递的请求操作(不管是WSARecv, WSASend, AcceptEx,DisconnextEx,...)必将返回,只不过有的成功,有的失败而已。

估计是你收到一次false,就退出线程了,根本就没有继续GetQueuedCompletionStatus,所以造成没有反应的错觉。
[/Quote]
感觉你说的不对啊。和我测试的结果不一样啊!
tech_study_00 2009-11-25
  • 打赏
  • 举报
回复
GetQueuedCompletionStatus对于一个无效的已经关闭的句柄是无效的。
ahniyilin 2009-11-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 myy 的回复:]
而GetQueuedCompletionStatus只会在断线那一次才会返回false,对于后续的send请求操作失败则没有反应的。

----

不是这样的,只要不关闭完成端口的句柄并且一直GetQueuedCompletionStatus,所有投递的请求操作(不管是WSARecv, WSASend, AcceptEx,DisconnextEx,...)必将返回,只不过有的成功,有的失败而已。

估计是你收到一次false,就退出线程了,根本就没有继续GetQueuedCompletionStatus,所以造成没有反应的错觉。
[/Quote]
哈哈!一语点破啊。。。我是关了句柄了哦!!
lijianli9 2009-11-25
  • 打赏
  • 举报
回复
wsasend都会返回的,即使对方断开了网络,完全端口线程队列的GetQueuedCompletionStatus函数会返回
dwIosize==0和本次的OperType是POST_SEND,这样就代表本次的send失败。
makui 2009-11-25
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 ahniyilin 的回复:]
我想你还是没有看明白我想问的问题吧?!
[/Quote]

当然看清楚你的问题了,
1。你问的你的处理方式有没有问题,我给你的回答是有问题,指出了问题产生的原因,而且还给出了解决方法。
2。既然你的处理方式是有问题的,第二个问题就没必要去回答了吧?

myy 2009-11-24
  • 打赏
  • 举报
回复
而GetQueuedCompletionStatus只会在断线那一次才会返回false,对于后续的send请求操作失败则没有反应的。

----

不是这样的,只要不关闭完成端口的句柄并且一直GetQueuedCompletionStatus,所有投递的请求操作(不管是WSARecv, WSASend, AcceptEx,DisconnextEx,...)必将返回,只不过有的成功,有的失败而已。

估计是你收到一次false,就退出线程了,根本就没有继续GetQueuedCompletionStatus,所以造成没有反应的错觉。

18,355

社区成员

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

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