网络编程(学习)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;
}
相关推荐
星火开发设计几秒前
C++ 数组:一维数组的定义、遍历与常见操作
java·开发语言·数据结构·c++·学习·数组·知识
星幻元宇VR25 分钟前
走进公共安全教育展厅|了解安全防范知识
学习·安全·虚拟现实
知识分享小能手41 分钟前
Oracle 19c入门学习教程,从入门到精通, Oracle 表空间与数据文件管理详解(9)
数据库·学习·oracle
梁辰兴2 小时前
计算机网络基础:虚拟专用网
服务器·网络·计算机网络·vpn·虚拟专用网·计算机网络基础·梁辰兴
浅念-2 小时前
C语言小知识——指针(3)
c语言·开发语言·c++·经验分享·笔记·学习·算法
hkNaruto3 小时前
【AI】AI学习笔记:LangGraph 与 LangChain的关系以及系统性学习路线选择
笔记·学习·langchain
jrlong3 小时前
DataWhale大模型基础与量化微调task3学习笔记(第 5章:深入大模型架构_MoE 架构解析)
笔记·学习
极安代理3 小时前
HTTP代理是什么?作用与场景全面解析
网络·网络协议·http
就爱吃香菜14 小时前
跨越网络的连接艺术:实战基于 SSE 传输层的远程 MCP 服务部署,实现云端 AI 与本地资产联动
网络·人工智能
wdfk_prog5 小时前
[Linux]学习笔记系列 --[drivers][base]map
linux·笔记·学习