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

第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 3000
void 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 1024
void ErrorHanding(char * message);
#define TTL 64

void 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 1024
void 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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值