【读书笔记】TCP/IP网络编程 第14章 多播、广播

来源:互联网 发布:查手机mac地址 编辑:程序博客网 时间:2024/05/17 00:08

第14章 多播、广播


多播数据传输方式及流量方面的特点:

  • 多播服务器端针对特定的多播组,只发送一次数据
  • 即使只发送一次数据,该组内的所有客户端都会受到数据(路由器负责复制文件并传递到主机)
  • 多播组数可在IP地址范围内任意增加
  • 加入特定的多播组,就可接收发往该组的数据

TTL(time to live):

其值大小决定了数据包传递的距离,每经过一个路由器值就减一,TTL变为0则无法被传递,只能销毁了。


多播与广播的区别:

多播即使在跨越不同网络的情况下,只要加入多播组就能接收数据。相反,广播只能向同一网络中的主机传输数据。

  • 直接广播与本地广播区别:

直接广播(direct broadcast)是指Host部分全为1的广播地址。如:192.168.224.31。当某机器发出目的地址为直接广播(如:192.168.224.31)时,路由器通过查找路由表可以转发,直到该网段。当然,这需要在路由器接口上enable direct broadcast。直接广播在跨路由DHCP,TFTP等应用有着重要的作用。 本地广播(local broadcast)是指255.255.255.255。当某机器发出目的地址为本地广播时,路由器不会转发该包。所以该包只能限制在本网段,达到隔离广播,消除广播风暴的目的,所以称之为本地广播。


广播发送端:

#include "stdafx.h"#include <winsock2.h>#include <stdio.h>#include <iostream>#include <ws2tcpip.h>using namespace::std;#define BUF_SIZE 3000void ErrorHanding(char * message);void main(){    WSADATA wsaData;    SOCKET send_sock;    SOCKADDR_IN broad_adr;    FILE * fp;    char buf[BUF_SIZE];    int so_brd = 1;    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)//加载库并获取库信息填至wsaData        ErrorHanding("socket start error!");    send_sock = socket(PF_INET, SOCK_DGRAM, 0);//流式套接字,IPV4:TCP    //设置地址端口    memset(&broad_adr, 0, sizeof(broad_adr));    broad_adr.sin_family = AF_INET;    broad_adr.sin_addr.S_un.S_addr = inet_addr("255.255.255.255");    broad_adr.sin_port = htons(6000);    //利用套接字IP_MULTICAST_TTL设置TTL    setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (char *)&so_brd, sizeof(so_brd));    //打开传输数据文件    if ((fp=fopen("TCPSrv.cpp","r"))==NULL)        ErrorHanding("file open error!");    while (!feof(fp))    {        fgets(buf, BUF_SIZE, fp);        sendto(send_sock, buf, strlen(buf), 0, (SOCKADDR*)&broad_adr, sizeof(broad_adr));//向地址发送数据        Sleep(1000);    }    closesocket(send_sock);    WSACleanup();    return ;}void ErrorHanding(char * message){    cout << message << endl;    exit(1);}

广播接收端:

#include "stdafx.h"#include <winsock2.h>#include <stdio.h>#include <iostream>#include <ws2tcpip.h>using namespace::std;#define BUF_SIZE 3000 void ErrorHanding(char * message);void main(){    WSADATA wsaData;    SOCKET recv_sock;    char buf[BUF_SIZE];    int str_len;    SOCKADDR_IN adr;    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)//加载库并获取库信息填至wsaData        ErrorHanding("socket start error!");    recv_sock = socket(PF_INET, SOCK_DGRAM, 0);//流式套接字,IPV4:UDP    //设置地址端口    memset(&adr, 0, sizeof(adr));    adr.sin_family = AF_INET;    adr.sin_addr.S_un.S_addr = INADDR_ANY;    adr.sin_port = htons(6000);    //套接字绑定地址端口    if (bind(recv_sock, (SOCKADDR*)&adr, sizeof(adr)) == SOCKET_ERROR)        ErrorHanding("socket bind error!");    while (1)    {        //recvfrom参数:套接字,缓冲区,缓冲区大小,可选参数,存发送端地址信息的结构体,前一参数大小值变量地址        str_len = recvfrom(recv_sock, buf, BUF_SIZE-1, 0, NULL, 0);//不需要知道传输数据的主机地址信息 :第5/6个参数设为null 0        if (str_len<0)            break;        buf[str_len] = 0;        fputs(buf, stdout);    }    closesocket(recv_sock);    WSACleanup();    return;}void ErrorHanding(char * message){    cout << message << endl;    exit(1);}

广播效果:

这里写图片描述


多播发送者:

#include "stdafx.h"#include <winsock2.h>#include <stdio.h>#include <iostream>#include <ws2tcpip.h>using namespace::std;#define BUF_SIZE 1024void ErrorHanding(char * message);#define TTL 64void main(){    WSADATA wsaData;    SOCKET hSendSock;    SOCKADDR_IN mulAdr;    int timeLive = TTL;    FILE * fp;    char buf[BUF_SIZE];    int adrSz;    int strLen, fdNum, i;    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)//加载库并获取库信息填至wsaData        ErrorHanding("socket start error!");    hSendSock = socket(PF_INET, SOCK_DGRAM, 0);//流式套接字,IPV4:TCP    //设置地址端口    memset(&mulAdr, 0, sizeof(mulAdr));    mulAdr.sin_family = AF_INET;    mulAdr.sin_addr.S_un.S_addr = inet_addr("244.1.1.2");    mulAdr.sin_port = htons(6000);    //利用套接字IP_MULTICAST_TTL设置TTL    setsockopt(hSendSock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&timeLive, sizeof(timeLive));    //打开传输数据文件    if ((fp=fopen("TCPSrv.cpp","r"))==NULL)        ErrorHanding("file open error!");    while (!feof(fp))    {        fgets(buf, BUF_SIZE, fp);        sendto(hSendSock, buf, strlen(buf),0,(SOCKADDR*)&mulAdr,sizeof(mulAdr));//向多播地址发送数据        Sleep(2000);    }    closesocket(hSendSock);    WSACleanup();    return ;}void ErrorHanding(char * message){    cout << message << endl;    exit(1);}

多播接收端:

#include "stdafx.h"#include <winsock2.h>#include <stdio.h>#include <iostream>#include <ws2tcpip.h>using namespace::std;#define BUF_SIZE 1024void ErrorHanding(char * message);void main(){    WSADATA wsaData;    SOCKET hRecvSock;    char buf[BUF_SIZE];    int strLen;    SOCKADDR_IN adr;    ip_mreq joinAdr;//多播组地址信息    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)//加载库并获取库信息填至wsaData        ErrorHanding("socket start error!");    hRecvSock = socket(PF_INET, SOCK_DGRAM, 0);//流式套接字,IPV4:UDP    //设置地址端口    memset(&adr, 0, sizeof(adr));    adr.sin_family = AF_INET;    adr.sin_addr.S_un.S_addr = INADDR_ANY;    adr.sin_port = htons(6000);    //套接字绑定地址端口    if (bind(hRecvSock, (SOCKADDR*)&adr, sizeof(adr)) == SOCKET_ERROR)        ErrorHanding("socket bind error!");    //设置多播组信息    joinAdr.imr_multiaddr.S_un.S_addr = inet_addr("244.1.1.2");    joinAdr.imr_interface.S_un.S_addr = INADDR_ANY;    //利用套接字ip_add_membership加入多播组    if (setsockopt(hRecvSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&joinAdr, sizeof(joinAdr)) == SOCKET_ERROR)        ErrorHanding("setsockopt() error !");    while (1)    {        //recvfrom参数:套接字,缓冲区,缓冲区大小,可选参数,存发送端地址信息的结构体,前一参数大小值变量地址        strLen = recvfrom(hRecvSock, buf, BUF_SIZE, 0, NULL,0);//不需要知道传输数据的主机地址信息 :第5/6个参数设为null 0        if (strLen<0)            break;        fputs(buf, stdout);    }    closesocket(hRecvSock);    WSACleanup();    return;}void ErrorHanding(char * message){    cout << message << endl;    exit(1);}
阅读全文
0 0