一个关于IOCP发送数据的问题? 本帖最后由 mni2005 于 2012-09-21 14:22:30 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 两点理解都是正确的。如果你在一个套接字上投递多个请求,包括读和写,则一个socket就对应多个overlapped对象,但是否会并发,要看你开了多少个线程,如果你只开一个,则不会并发,但顺序无法保证,所以应该在一个套接字上最多投递一个读和一个写。 自己顶下……!!!!!!!!!!!//===================================以下为csdn广告,与本人无关==================================// 加个序号?如果出现分包,你的序号都不知道在哪里去了,你凭什么认定最前面就是序号而不是数据?你知道iocp乱序问题吗? 如果序号放在overlapped里面而不是数据包里面呢,异步操作完成后,直接从本地内存取 overlapped结构只在本地使用,不发送到对方。 lpOverlapped参数,就是相当于一次IO操作,你投一个POST 过去就对应 一次GetQueuedCompletionStatus返回. 你应该控制一下.不能send太多.如果客户端一直不收数据,就得出问题.你应该做个计数.一个客户不能太多.除非他接收了数据. 是在本地用,你投递了多个异步I/O,在每个overlapped里面标明序号,这些操作分别完成的时候,自然能分清前后顺序了。 你自己分清有什么用,比如客户端多次send,需要服务端分清顺序,而不是客户端自己分清顺序。自己分清顺序意义何在?你的理论在实际应用中用过吗?有否做过压力测试? 这个理论你在哪里知道的,实际调试过吗?追问楼主一点,这里说的是tcp而不是udp吧? TCP,IOCP一般都是用来玩TCP,玩UDP的少吧? send函数只是把数据发送网卡缓冲区,就算发送成功,客户能不能接收到是另外一回事!! 非要在实际应用中用过,做过压力测试才能来CSDN讨论是么? 想到什么就说什么,是对是错大家一起讨论一下就行了。 何必这么咄咄逼人? 你是权威? 不容侵犯?PS:细想了一下,上面那个帖子我说的确实不对。 如果客户不收.你的send就不会返回的.请问你几千个客户你不停SEND 你的WINDOWS内存锁定是会不够啊. 不明白这什么意思.服务端与客户端SEND 是没有关系的啊.你处理你的.这客户与服务器没有关系啊.他自己发错了难道你帮他处理错误.udp也不是这样处理的哈. 回楼上,这里在讨论iocp乱序的问题。你回复这三贴,都是不对的。你的理解偏差很大的,对网络编程。 可能我水平太差哈.你水平高说的话我们都听不懂.....你的都读不通.你自己加个序列不就不乱序啦嘛.IOCP是保证你收到的不乱序的.只是在通知你的线程的时候序列不一致. 个人理解:1、接收时一个socket保证一次Recv投递就可以,如果是TCP就不会乱序的,如果是UDP就有可能乱序;处理时即时多线程也不会乱序,因为同一个socket在同一时刻只有一个线程在处理接收数据,如果接收的数据不乱序,处理就不会乱序;而是否乱序与你选择的通信协议有关(TCP还是UDP)2、发送时最好也保证一个socket同时只投递一个Send,而处理线程中接收到Send事件表示的是此socket可以准备处理send事件发来的通知,一般处理线程根据此通知来再次发送数据以上是个人理解,不当这处请大家指出 我这里只说TCP.是在投wsarev 的ovler上加序号. 先投肯定先得到TCP数据..收到合理的数据自己处理里面的序列啊.这样是肯定可以的.你可能想的是客户端加序列号.这是UDP 这样你还是不能解决IOCP 多线程 乱序问题.UDP 你得加协议处理包头+序列号+内容.而且UDP是 块数据,不可能说到你说的收到1000另外收到24.那是TCP流的情况. 你到底是在说TPC还是UDP IOCP 一般是做TCP UDP 没必要. 这样会有什么问题??? 先投先到.切换线程与收数据有什么关系.你把数据按序号收了然后自己处理逻辑层啊.其实IOCP一个REV就行啦.我感觉.你并发大了.多了没意思 我并发五千每秒只能发7次数据,这时CPU占用在20%左右. 我的意思基于如下假设(因为我不这样假设的话,几乎就是不行的):一个套接字上投递多个IO,是一个确定的数目,而不是无限的。比如wsasend,如果一有数据就投递一个,那压力测试下,系统内存肯定耗尽,这不能算是一个合格的服务端。一般我认为服务端,都应该有输入输出缓存,我们以每个套接字投递两个读和两个写为例,假设现在缓存里面有10条数据需要发送,第一次连接投递两个wsasend,当发送完成之后,将在另外的线程(GetQueuedCompletionStatus所在的线程)得到通知,于是接着进行下一次wsasend(因为还有数据需要发送),那么会出现在不同线程并发对同一个套接字调用wsasend的情况,这是msdn证实了的,不行的(行也不能用,因为无法保证顺序,需要自己加锁)。同样,wsarecv也一样,一开始发起两个wsarecv,当有数据收到之后,会出现在不同线程并发对同一个套接字调用wsarecv的情况,这也是msdn证实了的,不行的(同样,就算行也不能用,还是因为顺序的问题,解决办法类似,把分配序号与wsarecv一起互斥即可)。在前面的假设下,有如下问题:投递多个wsarecv,编程的上难度相当大,因为收到数据之后,肯定要马上投递下一个wsarecv,如果不这样,服务端的吞吐量没办法保证。那么此时如何处理已经收到的数据呢?注意,此时你不一定能组包,因为如果前面的wsarecv还没反馈回来怎么办(数据是收到了,但调用GetQueuedCompletionStatus的线程还没有得到调度,这是完全有可能的,线程的调度就是这样)?那么是不是要弄个链表来保存已经收到,但还没有被组包的数据?如果加了这个链表,那加锁解锁无法避免。另外,组包的时候,还要遍历数据接收链表,以确定是否可以组包。再者,这样的设计肯定不会提高服务端的吞吐量,也不会提高某个套接字的吞吐量,比如现在10个套接字,每个套接字投递一个wsarecv,那么每个套接字的IO请求占所有请求的1/10;如果改为每个套接投递两个wasrecv,那么每个套接字的IO请求还是占所有请求的1/10 = 2/20。如果这些都做好了,我认为在同一个套接字上投递多个读和写也是可行的,前面我没有看清楚是在wsarecv加序号,而不是wsasend,但解决这些问题值得吗?它带来什么好处呢? 鼠标滚动放大图片 问题 editlistctrl 如何设置fullrowselect C++中有没有类似Java中的Map? 串口编程 IRP_MJ_READ问题 VC中使用定时器调用SQL SERVER 的存储过程 新手:对话框中的OnKeyDown,什么时候能受到呀? 《Windows程式设计》中的一个例子,不能运行,是什么原因啊? 我想实现切换视图的功能,大家帮个忙:) VC编译的程序出现0X000007b错误 VC++高手们:你们用VC++做的第一个程序是什么(除Hello外) MFC你学了多久? VS2010怎么添加消息处理函数
如果出现分包,你的序号都不知道在哪里去了,你凭什么认定最前面就是序号而不是数据?
你知道iocp乱序问题吗?
如果序号放在overlapped里面而不是数据包里面呢,异步操作完成后,直接从本地内存取
GetQueuedCompletionStatus返回. 你应该控制一下.不能send太多.如果客户端一直不收数据,就得出问题.
你应该做个计数.一个客户不能太多.除非他接收了数据.
是在本地用,你投递了多个异步I/O,在每个overlapped里面标明序号,这些操作分别完成的时候,自然能分清前后顺序了。
自己分清顺序意义何在?
你的理论在实际应用中用过吗?有否做过压力测试?
这个理论你在哪里知道的,实际调试过吗?追问楼主一点,这里说的是tcp而不是udp吧?
send函数只是把数据发送网卡缓冲区,就算发送成功,客户能不能接收到是另外一回事!!
非要在实际应用中用过,做过压力测试才能来CSDN讨论是么? 想到什么就说什么,是对是错大家一起讨论一下就行了。 何必这么咄咄逼人? 你是权威? 不容侵犯?PS:细想了一下,上面那个帖子我说的确实不对。
不明白这什么意思.服务端与客户端SEND 是没有关系的啊.你处理你的.
这客户与服务器没有关系啊.他自己发错了难道你帮他处理错误.udp也不是这样处理的哈.
你的都读不通.
你自己加个序列不就不乱序啦嘛.IOCP是保证你收到的不乱序的.只是在通知你的线程的时候序列不一致.
1、接收时一个socket保证一次Recv投递就可以,如果是TCP就不会乱序的,如果是UDP就有可能乱序;处理时即时多线程也不会乱序,因为同一个socket在同一时刻只有一个线程在处理接收数据,如果接收的数据不乱序,处理就不会乱序;而是否乱序与你选择的通信协议有关(TCP还是UDP)
2、发送时最好也保证一个socket同时只投递一个Send,而处理线程中接收到Send事件表示的是此socket可以准备处理send事件发来的通知,一般处理线程根据此通知来再次发送数据
以上是个人理解,不当这处请大家指出
是在投wsarev 的ovler上加序号. 先投肯定先得到TCP数据..收到合理的数据自己处理里面的序列啊.这样是肯定可以的.
你可能想的是客户端加序列号.这是UDP 这样你还是不能解决IOCP 多线程 乱序问题.UDP 你得加协议处理包头+序列号+内容.而且UDP是 块数据,不可能说到你说的收到1000另外收到24.那是TCP流的情况.
还是UDP IOCP 一般是做TCP
UDP 没必要.
你把数据按序号收了然后自己处理逻辑层啊.其实IOCP一个REV就行啦.我感觉.你并发大了.多了没意思 我并发五千每秒只能发7次数据,这时CPU占用在20%左右.
一个套接字上投递多个IO,是一个确定的数目,而不是无限的。比如wsasend,如果一有数据就投递一个,那压力测试下,系统内存肯定耗尽,这不能算是一个合格的服务端。一般我认为服务端,都应该有输入输出缓存,我们以每个套接字投递两个读和两个写为例,假设现在缓存里面有10条数据需要发送,第一次连接投递两个wsasend,当发送完成之后,将在另外的线程(GetQueuedCompletionStatus所在的线程)得到通知,于是接着进行下一次wsasend(因为还有数据需要发送),那么会出现在不同线程并发对同一个套接字调用wsasend的情况,这是msdn证实了的,不行的(行也不能用,因为无法保证顺序,需要自己加锁)。同样,wsarecv也一样,一开始发起两个wsarecv,当有数据收到之后,会出现在不同线程并发对同一个套接字调用wsarecv的情况,这也是msdn证实了的,不行的(同样,就算行也不能用,还是因为顺序的问题,解决办法类似,把分配序号与wsarecv一起互斥即可)。在前面的假设下,有如下问题:
投递多个wsarecv,编程的上难度相当大,因为收到数据之后,肯定要马上投递下一个wsarecv,如果不这样,服务端的吞吐量没办法保证。那么此时如何处理已经收到的数据呢?注意,此时你不一定能组包,因为如果前面的wsarecv还没反馈回来怎么办(数据是收到了,但调用GetQueuedCompletionStatus的线程还没有得到调度,这是完全有可能的,线程的调度就是这样)?那么是不是要弄个链表来保存已经收到,但还没有被组包的数据?如果加了这个链表,那加锁解锁无法避免。另外,组包的时候,还要遍历数据接收链表,以确定是否可以组包。再者,这样的设计肯定不会提高服务端的吞吐量,也不会提高某个套接字的吞吐量,比如现在10个套接字,每个套接字投递一个wsarecv,那么每个套接字的IO请求占所有请求的1/10;如果改为每个套接投递两个wasrecv,那么每个套接字的IO请求还是占所有请求的1/10 = 2/20。如果这些都做好了,我认为在同一个套接字上投递多个读和写也是可行的,前面我没有看清楚是在wsarecv加序号,而不是wsasend,但解决这些问题值得吗?它带来什么好处呢?