比如我有两个缓冲区A和B,A大小1M,数据全部初始化为1,B大小2M,数据全部初始化为2
如果我挨着写两个WSASend把A,B通过同一个SOCKET发出去,客户端会收到1,2,2,1这样混乱的数据吗?

解决方案 »

  1.   

    TCP不会,因为TCP是保证连接的质量,而UDP可能会,因为UDP是没有保障的连接,速度快。
      

  2.   

    就是说只要我在WSASend收到完成通知之,不释放这两个缓冲区A和B,那客户端收到的数据(TCP)就应该是先1M的1,再1M的2了?
      

  3.   

    同一个线程中,不会乱序,多线程并发可能会例如,线程1先发A,发送成功了一部分(WSASend返回值小于1M),线程1会等待FD_WRITE
    线程2接着发送B,WSASend返回block,线程2也要等待FD_WRITE可是,当FD_WRITE发生的时候,线程1和线程2谁先执行到WSASend就是不可控的了
      

  4.   

    如果是完成端口的话,就更不能保证不乱序了当并发WSASend比较多时,系统缓冲区可能被填满,这时候必然有个WSASend会“部分完成”
    而“部分完成”的WSASend也会被GetQueuedCompletionStatus取到
    你会发现dwByteTransffered小于你投递的WSABUF的长度
    你必须针对这种情况继续投递WSASend将未完成的数据继续发送
    但你没办法保证在这两次WSASend操作之间不会被其他线程的WSASend插队
      

  5.   

    解决办法有两种思路:1、服务端客户端配合解决,服务端每次WSASend时,带一个序列号,客户端按序列号顺序组装2、服务端进行发送逻辑优化:收回各功能模块直接投递WSASend的权力,使用中间函数如“PostSend”替代
    PostSend不进行真正的WSASend投递,而是将数据附加到一个“待发送数据队列”之后;程序另外保证在IOCP上只投递一个并总是保持投递一个WSASend来循环发送“待发送列表队列”里的数据。“待发送列表”的访问要使用互斥
      

  6.   

    我现在遇到问题是这样,用的是完成端口,只有一个客户端连接,服务端连续用WSASend发送一个200字节的数据包,调用WSASend以后,把服务端的一个事件对象变为无信号,在工作线程收到通知以后,把事件对象置为有信号开始下一次发送,这样按理是一次性发送成功,不会因为多次WSASend而乱序的吧。实际情况是我在本机测试一切正常,但是把服务端放到服务器(SERVER 2003,与本机延迟也就几毫秒)上以后,问题就出现了,收到的数据变得很乱,不知道是什么情况
      

  7.   

    如果线程A、B同时GetQueuedCompletionStatus成功了
    线程A、B都会认为事件无信号,它们都会做同样的操作:
    把事件变成有信号、WSASend、把事件变成无信号不要并发投递WSASend,并发投递WSASend其实没有意义,它们还是会在系统缓冲区排队,而一旦系统缓冲区被填满,就会出现乱序——你还不如直接排队投递WSASend
      

  8.   

    我现在就是排队投递WSASend的,我有两个工作线程, 但是只有一个线程运行WSASend进行发包操作,调用WSASend以后,立即WaitForSingleObject,然后等工作线程收到完成通知把相应的事件变为有信号(我只投递了一个WSASend,不可能两个工作线程同时收到通知啊),然后发送线程会继续发送一个包。关键是我在本机运行正常,一放到服务器上作远程连接,就开始乱序....这个环境的改变会有影响吗?
      

  9.   

    肯定是你程序逻辑的问题
    你本机只有一颗CPU,你即使多线程也不会真正并发,而服务器是双CPU的,所以会出现并发问题IOCP的工作线程都使用同一个线程入口函数,你没办法定义哪个线程是发送线程,哪个线程是控制线程你的工作线程中,如果WSASend虽然是放在GetQueuedCompletionStatus之后的
    但你是否做了相应判断,只有GetQueuedCompletionStatus得到的是一次WSASend才继续投递WSASend呢?
    会不会有其他事件完成了,你也投递了WSASend?
      

  10.   

    我是在两个工作线程之外,另外有一个线程,从SOCKET列表中选择SOCKET进行WSASend的,与工作线程无关。
    服务器上确实是至强双核。
      

  11.   

    现在我基本上是从测试的角度来看的,相关于有工作线程WT1,WT2,然后另起一个线程T对连接上的客户端进行广播,每发出一个WSASend则用WaitForSingleObject等待,工作者线程里,如果收到刚才的WSASend完成通知,则把事件置为有信号,发送线程继续进行下一次发送。而且我也判断了NumberOfBytesTransfered,确实每次完成的发送数也是我之前WSASend的包大小200字节
    ,不解...
      

  12.   

    如果你只在线程T中进行WSASend投递,那么你的发送逻辑是很合理的,没有问题现在只能怀疑你进行WSASend投递时,传入的参数是否有问题了
    例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确
    建议你朝这个方向去检查
      

  13.   

    如果你只在线程T中进行WSASend投递,那么你的发送逻辑是很合理的,没有问题现在只能怀疑你进行WSASend投递时,传入的参数是否有问题了
    例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确
    建议你朝这个方向去检查
      

  14.   

    如果你只在线程T中进行WSASend投递,那么你的发送逻辑是很合理的,没有问题现在只能怀疑你进行WSASend投递时,传入的参数是否有问题了
    例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确
    建议你朝这个方向去检查