网络编程(学习)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;
}
相关推荐
一隅论数智2 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
XiHongShi20162 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
虎头金猫2 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
爱吃苹果的日记本2 天前
离散数学第六课
学习·离散数学
AI职业加油站2 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
旖旎夜光2 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
奇思妙想聪明勤奋的小羊2 天前
DeepAgents第5章:子Agent 与上下文隔离—让 Agent学会委派
人工智能·python·学习·语言模型
wuyk5552 天前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网
霍霍的袁2 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio