网络编程基础(四)

目录

前言

 二、多点通信

2.1 单播

2.2 广播

2.2.1 广播得发送端实现--》类似与UDP的客户端

 2.3 组播

2.3.1 组播发送端流程--》类似于UDP的客户端流程

 2.3.2 组播的接收端流程---》类似于UDP的服务器端流程


前言

多点通信


一、套接字选项得获取和设置

 int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);
 int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
        功能:获取或设置套接字在不同层级上的相关属性
        参数1:要获取或设置的套接字文件描述符
        参数2:表示要获取或设置的层
                应用层:SOL_SOCKET
                传输层TCP:IPPROTO_TCP
                传输层UDP:IPPROTO_UDP
                网络层:IPPROTO_IP
        参数3:当前层的属性名称,见下表所示
        参数4:要获取或设置的属性值的起始地址
        参数5:参数4的大小
        返回值:成功返回0,失败返回-1并置位错误码

 

1.代码演示

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //1、创建一个套接字文件描述符
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }
    
    //2、获取地址快速重用属性的值
    int res = -1;              //接收属性值
    int reslen = sizeof(res);  //接收属性的大小
    if(getsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &res, &reslen)==-1)
    {
        perror("getsockopt error");
        return -1;
    }

    //程序执行至此,就获取了默认是否能地址快速重用
    printf("res = %d\n", res);          //0表示默认不能快速重用

    //3\、设置地址能够快速重用
    int reuse = 1;
    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1)
    {
        perror("setsockopt error");
        return -1;
    }

    //4、再重新获取一次,判断是否设置成功
    res = -1;
    if(getsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &res, &reslen)==-1)
    {
        perror("getsockopt error");
        return -1;
    }

    //程序执行至此,就获取了默认是否能地址快速重用
    printf("res = %d\n", res);                  //1表示已经设置成功了


    return 0;
}

 二、多点通信

2.1 单播

1.主机之间存在的是一对一的通信方式,交换机以及路由器对数据只进行转发,不进行复制

2.每次只有两个实体之间进行相互通信,发送端和接收端都是唯一确定的

2.2 广播

1.广播是允许通信实体之间完成一对多的通信方式,网络对其中每一台发送数据的主机信息都进行无条件的复制后并转发给其他所有主机

2.所有主机都会收到广播消息(不管是都愿意接受)

3.广播只能由UDP通信方式来实现

4.广播消息,只能在当前网络下进行转播,不允许传过路由器

5.广播地址:网络号+255

6.官博分为发送端和接收端实现

2.2.1 广播得发送端实现--》类似与UDP的客户端

1、创建用于通信的套接字文件描述符:socket
2、设置该套接字允许发送广播消息:setsockopt     ---> SOL_SOCKET  ---> SO_BROADCAST
3、绑定IP地址和端口号(可选)
4、向广播地址发送数据:sendto
    广播地址IP:网络号 + 255
    端口号:与接收端保持一致
5、关闭套接字:close

代码实现:

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //1、创建用于通信的套接字文件描述符
    int rfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(rfd == -1)
    {
        perror("socket error");
        return -1;
    }


    //2、填充地址信息结构体:
    //ip:广播地址
    //port:与发送端保持一致
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    rin.sin_port = htons(6666);     //端口号
    rin.sin_addr.s_addr = inet_addr("192.168.125.255"); //广播ip地址

    //3、绑定端口号和IP地址(必须)
    if(bind(rfd, (struct sockaddr*)&rin, sizeof(rin)) == -1)
    {
        perror("bind error");
        return -1;
    }

    //4、接受发送端发来的消息:recvfrom
    char rbuf[128] = "";
    while(1)
    {
        //清空容器
        bzero(rbuf, sizeof(rbuf));

        //读取数据
        recv(rfd, rbuf, sizeof(rbuf), 0);

        //展示
        printf("收到广播消息:%s\n", rbuf);
        //判断广播是否结束

        if(strcmp(rbuf, "over") == 0)
        {
            break;
        }
    }

    //5、关闭套接字:close
    close(rfd);

    return 0;
}

2.2.2 广播的接收端--》类似于UDP的服务器端 

1、创建用于通信的套接字文件描述符
2、填充地址信息结构体:
    ip:广播地址
    port:与发送端保持一致
3、绑定端口号和IP地址(必须)
4、接受发送端发来的消息:recvfrom
5、关闭套接字:close

代码实现:

 

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //1、创建用于通信的套接字文件描述符
    int rfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(rfd == -1)
    {
        perror("socket error");
        return -1;
    }


    //2、填充地址信息结构体:
    //ip:广播地址
    //port:与发送端保持一致
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    rin.sin_port = htons(6666);     //端口号
    rin.sin_addr.s_addr = inet_addr("192.168.125.255"); //广播ip地址

    //3、绑定端口号和IP地址(必须)
    if(bind(rfd, (struct sockaddr*)&rin, sizeof(rin)) == -1)
    {
        perror("bind error");
        return -1;
    }

    //4、接受发送端发来的消息:recvfrom
    char rbuf[128] = "";
    while(1)
    {
        //清空容器
        bzero(rbuf, sizeof(rbuf));

        //读取数据
        recv(rfd, rbuf, sizeof(rbuf), 0);

        //展示
        printf("收到广播消息:%s\n", rbuf);
        //判断广播是否结束

        if(strcmp(rbuf, "over") == 0)
        {
            break;
        }
    }

    //5、关闭套接字:close
    close(rfd);

    return 0;
}

 2.3 组播

1.由于广播通信过程中,会占用大量的网络宽带,影响正常通信,如果通信的主机较少的话,可以引入组播

2.组播也是实现主机之间一对多的通信方式

3.要求所有接收端主机加入多播组,只有加入多播组的主机才能收到消息

4.对于发送端而言,只需向该多组播中发送消息即可,无需其他设置

5.组播也是使用UDP实现的

6.组播地址:D类网络【224.0.0.0---239.255.255.255】

7.组播也分为发送端和接收端

2.3.1 组播发送端流程--》类似于UDP的客户端流程

1、创建用于通信的套接字文件描述符:socket
2、绑定IP地址和端口号(可选)
3、向组播地址发送数据:sendto
    广播地址IP:【224.0.0.0 --- 239.255.255.255】
    端口号:与接收端保持一致
4、关闭套接字:close

代码实现:

 

#include<myhead.h>

int main(int argc, const char *argv[])
{
    //1、创建用于通信的套接字文件描述符:socket
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sfd == -1)
    {
        perror("socket error");
        return -1;
    }

    //2、绑定IP地址和端口号(可选)
    //3、向组播地址发送数据:sendto
    //广播地址IP:【224.0.0.0 --- 239.255.255.255】
    //端口号:与接收端保持一致
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    rin.sin_port = htons(5555);
    rin.sin_addr.s_addr = inet_addr("224.1.2.3");

    //数据的发送
   //发送数据
   char wbuf[128] = "";
   while(1)
   {
       //从终端获取数据
       fgets(wbuf, sizeof(wbuf), stdin);
       wbuf[strlen(wbuf)-1] = 0;

       //发送给广播消息
       sendto(sfd, wbuf, strlen(wbuf), 0, (struct sockaddr*)&rin, sizeof(rin));
       printf("发送成功\n");

       //判断发送的消息
       if(strcmp(wbuf, "over") == 0)
       {
           break;
       }
   }


    //5、关闭套接字:close
    close(sfd);

    return 0;
}

 2.3.2 组播的接收端流程---》类似于UDP的服务器端流程

1、创建用于通信的套接字文件描述符:socket
2、将该套接字加入多播组:setsockopt   --->  IPPROTO_IP    --> IP_ADD_MEMBERSHIP   
属性类型:
  struct ip_mreqn {
               struct in_addr imr_multiaddr; /* 组播地址 */
               struct in_addr imr_address;   /* 主机ip地址 */
               int            imr_ifindex;   /* 设备索引,可以通过 ip ad指令查看, 也可以填0,表示使用默认的索引*/
           };

3、填充地址信息结构体:
    ip:组播地址
    port:与发送端保持一致
4、绑定端口号和IP地址(必须)
5、接受发送端发来的消息:recvfrom
6、关闭套接字:close

代码实现:

#include<myhead.h>

int main(int argc, const char *argv[])
{
    
    //1、创建用于通信的套接字文件描述符:socket
    int rfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(rfd == -1)
    {
        perror("socket error");
        return -1;
    }

    //2、将该套接字加入多播组:setsockopt   --->  IPPROTO_IP    --> IP_ADD_MEMBERSHIP 
    struct ip_mreqn  imr;
    imr.imr_multiaddr.s_addr = inet_addr("224.1.2.3");
    imr.imr_address.s_addr = inet_addr("192.168.125.113");
    imr.imr_ifindex = 2;

    //设置套接字选项,加入多播组
    if(setsockopt(rfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr))==-1)
    {
        perror("setsockopt error");
        return -1;
    }

    //3、填充地址信息结构体:
    //ip:组播地址
    //port:与发送端保持一致
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    rin.sin_addr.s_addr = inet_addr("224.1.2.3");
    rin.sin_port = htons(5555);

    //4、绑定端口号和IP地址(必须)
    if(bind(rfd, (struct sockaddr*)&rin, sizeof(rin)) == -1)
    {
        perror("bind error");
        return -1;
    }


    //5、接受发送端发来的消息:recvfrom
    char rbuf[128] = "";
    while(1)
    {
        //清空容器
        bzero(rbuf, sizeof(rbuf));

        //读取数据
        recv(rfd, rbuf, sizeof(rbuf), 0);

        //展示
        printf("收到广播消息:%s\n", rbuf);
        //判断广播是否结束

        if(strcmp(rbuf, "over") == 0)
        {
            break;
        }
    }

    //6、关闭套接字:close
    close(rfd);



    return 0;
}

 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/658738.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

制作Dcoker镜像

文章目录 一、Docker构建镜像的原理1、镜像分层原理2、Docker的镜像结构3、分层存储原理4、构建命令与层的关系5、最终镜像的创建 二、docker commit 构建镜像1、使用场景2、手动制作yum版的nginx镜像2.1、启动一个centos容器&#xff0c;安装好常用的软件以及nginx2.2、关闭ng…

如何利用Firebase Hosting来托管网站

文章目录 如何利用Firebase Hosting来托管网站前提条件详细步骤1. 安装 Firebase CLI2. 登录 Firebase3. 初始化 Firebase 项目4. 准备网站文件5. 部署到 Firebase6. 配置自定义域名&#xff08;可选&#xff09; 常见问题 如何利用Firebase Hosting来托管网站 以下是更详细的…

硬盘的分区的类型及创建分区的步骤及交换分区、永久挂载的方法

业务层面&#xff1a;为了满足一定的需求所做的特定操作。 硬盘是什么&#xff0c;以及硬盘的作用。 硬盘&#xff1a;计算机的存储设备&#xff0c;一个或者多个带磁性的盘组成&#xff0c;可以在盘片上进行数据的读写 连接方式&#xff1a;内部设备 外部设备&#xff08;移…

linux /www/server/cron内log文件占用空间过大,/www/server/cron是什么内容,/www/server/cron是否可以删除

linux服务器长期使用宝塔自带计划任务&#xff0c;计划任务执行记录占用服务器空间过大&#xff0c;导致服务器根目录爆满&#xff0c;需要长期排查并删除 /www/server/cron 占用空间过大问题处理 /www/server/cron是什么内容&#xff1f;/www/server/cron是否可以删除&#xf…

低代码开发与人工智能技术在商品推荐系统中的应用

引言 低代码开发和人工智能技术的背景和重要性 随着数字化转型的深入&#xff0c;企业在信息技术领域面临着前所未有的挑战和机遇。快速变化的市场需求、日益复杂的技术环境以及高度竞争的商业环境&#xff0c;迫使企业不断寻求高效的开发和运营解决方案。低代码开发平台应运而…

【设计模式】JAVA Design Patterns——Dependency Injection(依赖注入模式)

&#x1f50d;目的 依赖注入是一种软件设计模式&#xff0c;其中一个或多个依赖项&#xff08;或服务&#xff09;被注入或通过引用传递到一个依赖对象&#xff08;或客户端&#xff09;中&#xff0c;并成为客户端状态的一部分。该模式将客户的依赖关系的创建与其自身的行为分…

3.Spring Cloud LoadBalancer 入门与使用

3.Spring Cloud LoadBalancer 入门与使用 1.什么是 LoadBalancer?1.1负载均衡分类1.2 常见负载均衡策略 2.为什么要学 LoadBalancer?3.如何使用?4.默认负载均衡策略5.随机负载均策略5.1 创建随机负载均衡器5.2 设置随机负载均衡器 (局部设置)5.3 设置全局负载均衡器 6.Nacos…

Codeforces Round 946 (Div. 3) A~G

A.Phone Desktop (枚举) 题意&#xff1a; 小 A A A的手机有一个桌面&#xff08;或称启动器&#xff09;。桌面可以由多个屏幕组成。每个屏幕表示为大小为 5 3 5 \times 3 53 的网格&#xff0c;即五行三列。 有 x x x 个应用程序的图标大小为 1 1 1 \times 1 11 个单…

C51单片机开发--库函数

知不足而奋进 望远山而前行 目录 系列文章目录 文章目录 前言 目标 内容 开发过程回顾 使用库函数点灯 什么是库函数? 面向库函数和面向寄存器开发 使用delay模块延时 总结 前言 在嵌入式系统开发中&#xff0c;使用库函数是提高开发效率、简化编程的重要手段之一…

学习Uni-app开发小程序Day21

学习了评分组件、自定义导航栏 评分组件uni-rate 这是需要达到的效果图&#xff0c;这里先分析下效果图&#xff0c; 1、图片是从布局中间弹出的&#xff0c;那这里就要用到uni-popup &#xff0c;设置type从中间弹出 2、这个弹出的顶部和上一张的顶部布局是一样的&#xff0c…

Axios的使用简单说明

axios 请求方式和参数 axios 可以发送 ajax 请求&#xff0c;不同的方法可以发送不同的请求: axios.get&#xff1a;发送get请求 axios.post&#xff1a;发送post请求 axios.put&#xff1a;发送put请求 axios.delete&#xff1a;发送delete请求 无论哪种方法&#xff0c;第一…

怎么使用Stable diffusion中的models

Stable diffusion中的models Stable diffusion model也可以叫做checkpoint model&#xff0c;是预先训练好的Stable diffusion权重&#xff0c;用于生成特定风格的图像。模型生成的图像类型取决于训练图像。 如果训练数据中从未出现过猫的图像&#xff0c;模型就无法生成猫的…

应急响应-网页篡改-典型处置案例

内部系统主页被篡改 事件背景 2019年11月13日&#xff0c;某单位发现其内部系统的主页被篡改&#xff0c;应急响应工程师到达现场后对被入侵服务器进行检查&#xff0c;发现对方采用某开源CMS和第三方phpstudy进行环境部署。由于phpstudy默认不开启Web日志记录&#xff0c;因…

【Pandas】深入解析`pd.read_json()`函数

【Pandas】深入解析pd.read_json()函数 &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#x…

SQL面试题练习 —— 计算次日留存率

题目 现有用户登录记录表&#xff0c;已经按照用户日期进行去重处理。以用户登录的最早日期作为新增日期&#xff0c;请计算次日留存率是多少。 样例数据 ----------------------- | user_id | login_date | ----------------------- | aaa | 2023-12-01 | | bbb …

负载箱:充电桩测试利器

随着新能源汽车的普及&#xff0c;充电桩的需求也在不断增长。为了保证充电桩的安全、稳定和高效运行&#xff0c;对其进行严格的测试是必不可少的。在这个过程中&#xff0c;负载箱就成为了充电桩测试的重要工具。 负载箱模拟电动汽车充电的设备&#xff0c;它可以模拟真实的充…

轻兔推荐 —— 一个好用的软件服务推荐平台

给大家推荐一个好用的的软件服务推荐平台&#xff1a;轻兔推荐 网站界面简洁大方&#xff0c;没有太多杂七杂八的功能和页面&#xff0c;有明暗主题色可以选择&#xff0c;默认为亮色&#xff0c;可在网站上方手动切换。 每工作日都会推荐一款软件&#xff0c;有时会加更&…

高铁Wifi是如何接入的?

使用PC端的朋友&#xff0c;请将页面缩小到最小比例&#xff0c;阅读最佳&#xff01; 在飞驰的高铁上&#xff0c;除了窗外一闪而过的风景&#xff0c;你是否好奇过&#xff0c;高铁Wifi信号如何连接的呢&#xff1f; 远动的火车可不能连接光纤吧&#xff0c;难道是连接的卫星…

深入理解python列表遍历:两种方法详解与实例

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、使用索引遍历列表 三、直接使用元素遍历列表 四、总结 一、引言 在编程过程…

python-数据可视化(总)

python-数据可视化 ** 数据可视化 指的是通过可视化表示来探索数据&#xff0c;它与数据挖掘**紧密相关&#xff0c;而数据挖掘指的是使用代码来探索数据集的规律和关联。数据集可以是用一行代码就能表示的小型数字列表&#xff0c;也可以是数以吉字节的数据 最流行的工具之一…