上一篇文章说明了如何用UDP多播实现屏幕广播,用这种方式可以大大减少数据传输量,但是现在还有一个问题:由于UDP数据包的大小有限制,所以如果要传输一张图片需要把图片划分成若干个部分分开发送,但是UDP是属于不可靠的传输,它并不能保证这些数据包可以顺序到达接收方,传输过程中可能会出现丢包或乱序的情况,导致接收方不能接收到完整图片,在网上搜索的用UDP可靠传输的方法大多数都是接收方在接收出现问题的时候向发送方请求重新发送,但这种解决方案显然不实用于屏幕广播这种一对多的传输模式。最后在CSDN上找到了一种解决方法,这里简要说明一下思路。(CSDN地址:http://download.csdn.net/detail/ztxzyr/3824829)
这里要用到一种UDP数据包的数据结构,这里给出我自己的定义:
#define MAXBUFSIZE (32 * 1024) //缓冲区最大值 //UDP数据包 typedef struct _UDPPACKAGE{ DWORD dwIndex; //当前包序号 DWORD dwTotalSize; //数据总大小 bool bFinish; //是否已结束 char buf[MAXBUFSIZE]; //数据缓冲区 DWORD dwDataSize; //缓冲区数据大小 }UDPPACKAGE, *PUDPPACKAGE;
这里假设要传送的图片大小是128KB,由于数据包中数据缓冲区大小是32KB,所以要分成4个udp包,它们的序号依次是0、1、2、3,前三个数据包的bFinish设置为false,最后一个bFinish设置为true。发送方采用以上这种数据结构把数据打包发送出去。剩下的工作由接收方负责。
接收方接收数据的方法如下:首先设置一个当前期望收到的数据包序号dwCurrentIndex,当第一次接收时由于之前从未接收过图片,所以设置为0,表示希望收到序号是0的序号,当收到一个数据包的时候判断该包的序号与期望收到的序号是否相等,如果相等,就把这个包的数据写入文件,并且使dwCurrentIndex加1,然后判断这个包是不是最后一个包,即bFinish是否为真,如果为真则文件接收完毕,否则继续接收;如果不相等的话,就把dwCurrentIndex设置为0,同时把文件指针移动到文件开始处,表示下一个希望收到图片的第一个包,上一张图片剩余的包已不再有效。具体流程如下:
整个接收过程用一句话来说就是:接收方只接收按序到达的图片,不按顺序来的都不处理。因为发送方是不断发送图片,所以有一张或几张图片没有接收不会造成太大影响,这样接收图片不完整的问题也就可以解决了。