连续对一个SOCKET进行WSASend异步发送会乱序吗? 比如我有两个缓冲区A和B,A大小1M,数据全部初始化为1,B大小2M,数据全部初始化为2如果我挨着写两个WSASend把A,B通过同一个SOCKET发出去,客户端会收到1,2,2,1这样混乱的数据吗? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 TCP不会,因为TCP是保证连接的质量,而UDP可能会,因为UDP是没有保障的连接,速度快。 就是说只要我在WSASend收到完成通知之,不释放这两个缓冲区A和B,那客户端收到的数据(TCP)就应该是先1M的1,再1M的2了? 同一个线程中,不会乱序,多线程并发可能会例如,线程1先发A,发送成功了一部分(WSASend返回值小于1M),线程1会等待FD_WRITE线程2接着发送B,WSASend返回block,线程2也要等待FD_WRITE可是,当FD_WRITE发生的时候,线程1和线程2谁先执行到WSASend就是不可控的了 如果是完成端口的话,就更不能保证不乱序了当并发WSASend比较多时,系统缓冲区可能被填满,这时候必然有个WSASend会“部分完成”而“部分完成”的WSASend也会被GetQueuedCompletionStatus取到你会发现dwByteTransffered小于你投递的WSABUF的长度你必须针对这种情况继续投递WSASend将未完成的数据继续发送但你没办法保证在这两次WSASend操作之间不会被其他线程的WSASend插队 解决办法有两种思路:1、服务端客户端配合解决,服务端每次WSASend时,带一个序列号,客户端按序列号顺序组装2、服务端进行发送逻辑优化:收回各功能模块直接投递WSASend的权力,使用中间函数如“PostSend”替代PostSend不进行真正的WSASend投递,而是将数据附加到一个“待发送数据队列”之后;程序另外保证在IOCP上只投递一个并总是保持投递一个WSASend来循环发送“待发送列表队列”里的数据。“待发送列表”的访问要使用互斥 我现在遇到问题是这样,用的是完成端口,只有一个客户端连接,服务端连续用WSASend发送一个200字节的数据包,调用WSASend以后,把服务端的一个事件对象变为无信号,在工作线程收到通知以后,把事件对象置为有信号开始下一次发送,这样按理是一次性发送成功,不会因为多次WSASend而乱序的吧。实际情况是我在本机测试一切正常,但是把服务端放到服务器(SERVER 2003,与本机延迟也就几毫秒)上以后,问题就出现了,收到的数据变得很乱,不知道是什么情况 如果线程A、B同时GetQueuedCompletionStatus成功了线程A、B都会认为事件无信号,它们都会做同样的操作:把事件变成有信号、WSASend、把事件变成无信号不要并发投递WSASend,并发投递WSASend其实没有意义,它们还是会在系统缓冲区排队,而一旦系统缓冲区被填满,就会出现乱序——你还不如直接排队投递WSASend 我现在就是排队投递WSASend的,我有两个工作线程, 但是只有一个线程运行WSASend进行发包操作,调用WSASend以后,立即WaitForSingleObject,然后等工作线程收到完成通知把相应的事件变为有信号(我只投递了一个WSASend,不可能两个工作线程同时收到通知啊),然后发送线程会继续发送一个包。关键是我在本机运行正常,一放到服务器上作远程连接,就开始乱序....这个环境的改变会有影响吗? 肯定是你程序逻辑的问题你本机只有一颗CPU,你即使多线程也不会真正并发,而服务器是双CPU的,所以会出现并发问题IOCP的工作线程都使用同一个线程入口函数,你没办法定义哪个线程是发送线程,哪个线程是控制线程你的工作线程中,如果WSASend虽然是放在GetQueuedCompletionStatus之后的但你是否做了相应判断,只有GetQueuedCompletionStatus得到的是一次WSASend才继续投递WSASend呢?会不会有其他事件完成了,你也投递了WSASend? 我是在两个工作线程之外,另外有一个线程,从SOCKET列表中选择SOCKET进行WSASend的,与工作线程无关。服务器上确实是至强双核。 现在我基本上是从测试的角度来看的,相关于有工作线程WT1,WT2,然后另起一个线程T对连接上的客户端进行广播,每发出一个WSASend则用WaitForSingleObject等待,工作者线程里,如果收到刚才的WSASend完成通知,则把事件置为有信号,发送线程继续进行下一次发送。而且我也判断了NumberOfBytesTransfered,确实每次完成的发送数也是我之前WSASend的包大小200字节,不解... 如果你只在线程T中进行WSASend投递,那么你的发送逻辑是很合理的,没有问题现在只能怀疑你进行WSASend投递时,传入的参数是否有问题了例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确建议你朝这个方向去检查 如果你只在线程T中进行WSASend投递,那么你的发送逻辑是很合理的,没有问题现在只能怀疑你进行WSASend投递时,传入的参数是否有问题了例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确建议你朝这个方向去检查 如果你只在线程T中进行WSASend投递,那么你的发送逻辑是很合理的,没有问题现在只能怀疑你进行WSASend投递时,传入的参数是否有问题了例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确建议你朝这个方向去检查 MFC 规则DLL 请问这个托盘效果是怎么实现的? 如何取得经扩展后的控件大小 关于数据库编程的问题请高手指点 关于Edit!! 我想在工具栏里显示图片和文字`可是文字显示得太低了``请教`` 用Netmeeting的SDK时,完成的程序是不是一定要启动NETMEETING??可不可以不要启动? 把目录下的一批文件属性从只读改为可读,请问用什么命令呀 advanced installer卸载软件时保留一些文件 MFC 向游戏窗口发送ENTER按键消息,大部分没有效果 在OnInitDialog里能获取窗体的桌面坐标吗? 单文档的view视图里加了个树形图,给树形图加响应
线程2接着发送B,WSASend返回block,线程2也要等待FD_WRITE可是,当FD_WRITE发生的时候,线程1和线程2谁先执行到WSASend就是不可控的了
而“部分完成”的WSASend也会被GetQueuedCompletionStatus取到
你会发现dwByteTransffered小于你投递的WSABUF的长度
你必须针对这种情况继续投递WSASend将未完成的数据继续发送
但你没办法保证在这两次WSASend操作之间不会被其他线程的WSASend插队
PostSend不进行真正的WSASend投递,而是将数据附加到一个“待发送数据队列”之后;程序另外保证在IOCP上只投递一个并总是保持投递一个WSASend来循环发送“待发送列表队列”里的数据。“待发送列表”的访问要使用互斥
线程A、B都会认为事件无信号,它们都会做同样的操作:
把事件变成有信号、WSASend、把事件变成无信号不要并发投递WSASend,并发投递WSASend其实没有意义,它们还是会在系统缓冲区排队,而一旦系统缓冲区被填满,就会出现乱序——你还不如直接排队投递WSASend
你本机只有一颗CPU,你即使多线程也不会真正并发,而服务器是双CPU的,所以会出现并发问题IOCP的工作线程都使用同一个线程入口函数,你没办法定义哪个线程是发送线程,哪个线程是控制线程你的工作线程中,如果WSASend虽然是放在GetQueuedCompletionStatus之后的
但你是否做了相应判断,只有GetQueuedCompletionStatus得到的是一次WSASend才继续投递WSASend呢?
会不会有其他事件完成了,你也投递了WSASend?
服务器上确实是至强双核。
,不解...
例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确
建议你朝这个方向去检查
例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确
建议你朝这个方向去检查
例如LPWSABUF指针内容是否正确,LPOVERLAPPED指针内容是否正确
建议你朝这个方向去检查