本帖最后由 mni2005 于 2012-09-21 14:22:30 编辑

解决方案 »

  1.   

    两点理解都是正确的。如果你在一个套接字上投递多个请求,包括读和写,则一个socket就对应多个overlapped对象,但是否会并发,要看你开了多少个线程,如果你只开一个,则不会并发,但顺序无法保证,所以应该在一个套接字上最多投递一个读和一个写。
      

  2.   

    自己顶下……!!!!!!!!!!!//===================================以下为csdn广告,与本人无关==================================//
      

  3.   

    加个序号?
    如果出现分包,你的序号都不知道在哪里去了,你凭什么认定最前面就是序号而不是数据?
    你知道iocp乱序问题吗?
      

  4.   


    如果序号放在overlapped里面而不是数据包里面呢,异步操作完成后,直接从本地内存取
      

  5.   

    overlapped结构只在本地使用,不发送到对方。
      

  6.   

    lpOverlapped参数,就是相当于一次IO操作,你投一个POST 过去就对应 一次
    GetQueuedCompletionStatus返回.  你应该控制一下.不能send太多.如果客户端一直不收数据,就得出问题.
    你应该做个计数.一个客户不能太多.除非他接收了数据.
      

  7.   


    是在本地用,你投递了多个异步I/O,在每个overlapped里面标明序号,这些操作分别完成的时候,自然能分清前后顺序了。
      

  8.   

    你自己分清有什么用,比如客户端多次send,需要服务端分清顺序,而不是客户端自己分清顺序。
    自己分清顺序意义何在?
    你的理论在实际应用中用过吗?有否做过压力测试?
      

  9.   


    这个理论你在哪里知道的,实际调试过吗?追问楼主一点,这里说的是tcp而不是udp吧?
      

  10.   

    TCP,IOCP一般都是用来玩TCP,玩UDP的少吧?
      

  11.   


    send函数只是把数据发送网卡缓冲区,就算发送成功,客户能不能接收到是另外一回事!!
      

  12.   


    非要在实际应用中用过,做过压力测试才能来CSDN讨论是么? 想到什么就说什么,是对是错大家一起讨论一下就行了。 何必这么咄咄逼人? 你是权威? 不容侵犯?PS:细想了一下,上面那个帖子我说的确实不对。
      

  13.   

    如果客户不收.你的send就不会返回的.请问你几千个客户你不停SEND 你的WINDOWS内存锁定是会不够啊.
      

  14.   


    不明白这什么意思.服务端与客户端SEND 是没有关系的啊.你处理你的.
    这客户与服务器没有关系啊.他自己发错了难道你帮他处理错误.udp也不是这样处理的哈.
      

  15.   

    回楼上,这里在讨论iocp乱序的问题。你回复这三贴,都是不对的。你的理解偏差很大的,对网络编程。
      

  16.   

    可能我水平太差哈.你水平高说的话我们都听不懂.....
    你的都读不通.
    你自己加个序列不就不乱序啦嘛.IOCP是保证你收到的不乱序的.只是在通知你的线程的时候序列不一致.
      

  17.   

    个人理解:
    1、接收时一个socket保证一次Recv投递就可以,如果是TCP就不会乱序的,如果是UDP就有可能乱序;处理时即时多线程也不会乱序,因为同一个socket在同一时刻只有一个线程在处理接收数据,如果接收的数据不乱序,处理就不会乱序;而是否乱序与你选择的通信协议有关(TCP还是UDP)
    2、发送时最好也保证一个socket同时只投递一个Send,而处理线程中接收到Send事件表示的是此socket可以准备处理send事件发来的通知,一般处理线程根据此通知来再次发送数据
    以上是个人理解,不当这处请大家指出
      

  18.   

    我这里只说TCP.
    是在投wsarev 的ovler上加序号. 先投肯定先得到TCP数据..收到合理的数据自己处理里面的序列啊.这样是肯定可以的.
    你可能想的是客户端加序列号.这是UDP 这样你还是不能解决IOCP 多线程 乱序问题.UDP 你得加协议处理包头+序列号+内容.而且UDP是 块数据,不可能说到你说的收到1000另外收到24.那是TCP流的情况.
      

  19.   

    你到底是在说TPC
    还是UDP IOCP 一般是做TCP 
    UDP 没必要.
      

  20.   

    这样会有什么问题??? 先投先到.切换线程与收数据有什么关系.
    你把数据按序号收了然后自己处理逻辑层啊.其实IOCP一个REV就行啦.我感觉.你并发大了.多了没意思 我并发五千每秒只能发7次数据,这时CPU占用在20%左右. 
      

  21.   

    我的意思基于如下假设(因为我不这样假设的话,几乎就是不行的):
    一个套接字上投递多个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,但解决这些问题值得吗?它带来什么好处呢?