所谓屏幕广播,即是将指定计算机的的屏幕情况发送至多台电脑,使那些电脑也能够显示出指定计算机的电脑桌面,一般是在电子教室之类的教学软件中使用,最近为了在我们的一个软件中实现这个功能也费了不少功夫,所以在这里总结一下实现方法。
屏幕广播实现起来的方法其实也就是让指定计算机不断的屏幕截图,然后将这些图片发送至其他电脑,再让那些电脑收到图片后显示出来,这样屏幕广播的功能就实现了。今天我要说的只是如何发送这些图片,至于屏幕截图则有很多种方式在这里不作阐述。
之所以屏幕广播难以实现,主要就是屏幕广播是要把一张图片发送至多个电脑,如果采用TCP协议进行传输的话则必须向每一个电脑发送一张图片,这样假如一张图片是100KB,同时发送给10个计算机则需要将近1MB的数据传输量,这样大的数据量显然不能够在实际中应用,所以在屏幕广播时一般采用UDP协议来传输图片。
UDP是一种面向无连接的协议,之所以采用UDP是因为在UDP中有一种多播的技术,UDP多播通过向一个多播组中发送一个数据,那么只要是在这个多播组中的主机都可以收到同样的一份副本。这样如果要向10个主机发送一个100KB的图片的话,只要向一个多播组发送100KB的图片,那么其他主机都可以收到,这样即可以大大减小数据传输量。
编程实现起来也并不复杂,这里给出用C语言实现的思路和方法。实现多播只需要三步:1、创建UDP套接字;2、加入多播组;3开始发送(接收)
以下是具体实现:
1、首先把头文件和库包含进来
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
2、初始化Winsock库并创建UDP套接字
WSADATA WSAData; WORD wVersionRequested; wVersionRequested = MAKEWORD(2,2); if (WSAStartup(wVersionRequested,&WSAData)!=0) { printf("WinSock初始化失败 "); return -1; } SOCKET sSender; sSender = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF | WSA_FLAG_OVERLAPPED); if(sSender == INVALID_SOCKET) { WSACleanup(); return -1; }
3、加入多播组
//填充广播地址 sockaddr_in addrBroad; addrBroad.sin_family = AF_INET; addrBroad.sin_port = htons(8742); addrBroad.sin_addr.S_un.S_addr = inet_addr("224.8.8.1"); //加入广播组 SOCKET sRecver; sRecver = WSAJoinLeaf(sSender, (SOCKADDR*)&addrBroad, sizeof(addrBroad), NULL, NULL, NULL, NULL, JL_BOTH); if (sRecver == INVALID_SOCKET) { WSACleanup(); return -1; }
4、开始发送(接收)
发送时使用sendto函数
sendto(sSender, buf, sizeof(buf), 0, (struct sockaddr*)&addrBroad, sizeof(addrBroad);
接收时使用recvfrom函数
int len = sizeof(struct sockaddr); recvfrom(sRecver, buf, sizeof(buf), 0, (struct sockaddr*)&BroadAddr, &len);
这样多播基本上就已经实现了,不过还有几点要注意。首先是多播地址的概念,IP地址有一部分是划分为多播地址的,大家可以自己去网上搜索;其次是每一个主机只能加入一个多播组一次,再次加入的时候就会失败,所以在实验的时候要拿至少两台电脑,一台当接收方,一台当发送方;还有一点就是由于UDP并不保证数据能完整正确的到达接收方,所以这时候的屏幕广播就会有一个问题是接收的图片并不完整,解决方法会在下一篇中说明。