屏幕广播的实现(上)

  所谓屏幕广播,即是将指定计算机的的屏幕情况发送至多台电脑,使那些电脑也能够显示出指定计算机的电脑桌面,一般是在电子教室之类的教学软件中使用,最近为了在我们的一个软件中实现这个功能也费了不少功夫,所以在这里总结一下实现方法。

  屏幕广播实现起来的方法其实也就是让指定计算机不断的屏幕截图,然后将这些图片发送至其他电脑,再让那些电脑收到图片后显示出来,这样屏幕广播的功能就实现了。今天我要说的只是如何发送这些图片,至于屏幕截图则有很多种方式在这里不作阐述。

  之所以屏幕广播难以实现,主要就是屏幕广播是要把一张图片发送至多个电脑,如果采用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并不保证数据能完整正确的到达接收方,所以这时候的屏幕广播就会有一个问题是接收的图片并不完整,解决方法会在下一篇中说明。

参考资料:http://www.yesky.com/184/1777184.shtml

原文地址:https://www.cnblogs.com/GTKY/p/3675499.html