网络编程(学习)2024.9.3

目录

UDP多点通信

广播

理论

发送端--相当于udp客户端

接收端--相当于udp服务器

组播

理论

发送端

接收端

UDP多点通信

广播

理论

前面介绍的数据包发送方式只有一个接受方,称为单播

如果同时发给局域网中的所有主机,称为广播
只有用户数据报(使用UDP协议)套接字才能广播

一般被设计成局域网搜索协议

广播地址:以192.168.1.0 (255.255.255.0) 网段为例,最大的主机地址192.168.1.255代表该网段的广播地址

发到该地址的数据包被所有的主机接收

发送端--相当于udp客户端

1.socket;

2.setsockopt 允许发送广播

3.填充结构体

a.IP:广播地址

b.端口号,应该与接收端的端口号

4.发送广播

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char const *argv[])
{
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("创建套接字失败\n");
        return -1;
    }
    // 2.允许发送广播
    int flag = 1;
    socklen_t len = sizeof(flag);
    setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &flag, len);

    // 3.填充结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(8888);
    saddr.sin_addr.s_addr = inet_addr("192.168.50.255");
    socklen_t addrlen = sizeof(saddr);

#define N 64
    char buf[N];
    while (1)
    {
        memset(buf, 0, N);
        printf("请输入要输入的数据:");
        scanf("%s", buf);
        getchar();
        sendto(sockfd, buf, N, 0, (struct sockaddr *)&saddr, addrlen);
    }
    close(sockfd);
    return 0;
}

接收端--相当于udp服务器

1.socket;

2.填充结构体

a.IP:(0.0.0.0):本机所有可用IP--局域网IP、本地回环、广播地址、已加入的多播组

b.port:端口号 8888

3.bind

4.recvfrom

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char const *argv[])
{
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("创建套接字失败\n");
        return -1;
    }
    // 2.bind绑定IP和Port端口号
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    socklen_t addrlen = sizeof(saddr);

    if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("bind失败");
        return -1;
    }
    printf("bind成功\n");
    // 3.接收消息
#define N 64
    char buf[N];
    while (1)
    {
        int ret = recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&caddr, &addrlen);
        if (ret < 0)
        {
            perror("接收消息失败\n");
            close(sockfd);
            return -1;
        }
        else
        {
            printf("客户端ip:%s:%s\n", inet_ntoa(caddr.sin_addr), buf);
        }
    }
    close(sockfd);
    return 0;
}

组播

理论

接收方是局域网里的一部分

好处:避免了像广播那样带来的比较大的网络负载

组播地址:224.0.0.1~~239.255.255.254

发送端

1、socket;

2、填充结构体

a)IP:组播IP

b)port

3、发送

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char const *argv[])
{
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("创建套接字失败\n");
        return -1;
    }

    //2.填充结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(8888);
    saddr.sin_addr.s_addr = inet_addr("224.0.0.3");
    socklen_t addrlen = sizeof(saddr);

#define N 64
    char buf[N];
    while (1)
    {
        memset(buf, 0, N);
        printf("请输入要输入的数据:");
        scanf("%s", buf);
        getchar();
        sendto(sockfd, buf, N, 0, (struct sockaddr *)&saddr, addrlen);
    }
    close(sockfd);
    return 0;
}

接收端

1、socket

2、setsockopt 加入多播组

3、填充结构体

a)ip:0.0.0.0

b)PORT

4、bind

5、recvfrom
关于setsockopt要填充的结构体

struct ip_mreq

{

struct in_addr imr_multiaddr; /* 指定多播组IP */

struct in_addr imr_interface; /* 本地网卡地址,通常指定为 INADDR_ANY--0.0.0.0*/};

}

struct ip_mreq mreq;

//bzero(&mreq, sizeof(mreq));

mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.1");

mreq.imr_interface.s_addr = INADDR_ANY;

setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char const *argv[])
{
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("创建套接字失败\n");
        return -1;
    }

    // 加入多播组
    struct ip_mreq mreq;
    // bzero(&mreq, sizeof(mreq));
    mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.3");
    mreq.imr_interface.s_addr = INADDR_ANY;
    setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    socklen_t addrlen = sizeof(saddr);

    if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("bind失败");
        return -1;
    }
    printf("bind成功\n");
// 3.接收消息
#define N 64
    char buf[N];
    while (1)
    {
        int ret = recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&caddr, &addrlen);
        if (ret < 0)
        {
            perror("接收消息失败\n");
            close(sockfd);
            return -1;
        }
        else
        {
            printf("客户端ip:%s:%s\n", inet_ntoa(caddr.sin_addr), buf);
        }
    }
    close(sockfd);
    return 0;
}
相关推荐
yuzhangfeng1 小时前
【云计算物理网络】从传统网络到SDN:云计算的网络演进之路
网络·云计算
TDengine (老段)2 小时前
TDengine 中的关联查询
大数据·javascript·网络·物联网·时序数据库·tdengine·iotdb
zhu12893035562 小时前
网络安全的现状与防护措施
网络·安全·web安全
zhu12893035564 小时前
网络安全与防护策略
网络·安全·web安全
zhuyixiangyyds4 小时前
day21和day22学习Pandas库
笔记·学习·pandas
每次的天空4 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法
沫夕残雪4 小时前
HTTP,请求响应报头,以及抓包工具的讨论
网络·vscode·网络协议·http
π2704 小时前
爬虫:网络请求(通信)步骤,http和https协议
网络·爬虫
背影疾风5 小时前
C++学习之路:指针基础
c++·学习
zhu12893035566 小时前
网络安全基础与防护策略
网络·安全·web安全