2024.12.30(多点通信)

作业:
1、将广播发送和接收端实现一遍,完成一个发送端发送信息,对应多个接收端接收信息实验。

发送端

#include <myhead.h>#define PORT 8888
#define IP "192.168.124.255"int main(int argc, const char *argv[])
{//1、将广播发送和接收端实现一遍,//完成一个发送端发送信息,对应多个接收端接收信息实验。//1.创建套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd == -1){perror("socket");return -1;}//设置允许广播int k = 11;if(setsockopt(oldfd,SOL_SOCKET,SO_BROADCAST,&k,sizeof(k))==-1){perror("setsockopt");return -1;}printf("允许广播设置成功\n");struct sockaddr_in broadcast = {.sin_family = AF_INET,.sin_port = htons(PORT), 	//发送到该端口.sin_addr.s_addr = inet_addr(IP)};char buff[1024];while(1){fgets(buff,sizeof(buff),stdin);sendto(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&broadcast,sizeof(broadcast));if(strcmp(buff,"quit")==0){printf("发送端退出\n");break;}}close(oldfd);return 0;
}

接收端

#include <myhead.h>
#define PORT 8888
#define IP "192.168.124.255"int main(int argc, const char *argv[])
{//1.创建套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd == -1){perror("socket");return -1;}//填充广播地址信息结构体struct sockaddr_in send = {.sin_family = AF_INET,.sin_port = htons(PORT),.sin_addr.s_addr = inet_addr(IP)};if(bind(oldfd,(struct sockaddr *)&send,sizeof(send))==-1){perror("bind");return -1;}//接收消息char buff[1024];while(1){recvfrom(oldfd,buff,sizeof(buff),0,NULL,NULL);printf("%s",buff);}return 0;
}

2、使用多线程基于TCP协议的并发执行,一个服务器对应多个客户端实现通信实验。

服务器

#include <myhead.h>
#define PORT 8888
#define IP "192.168.124.123"void *fun(void *fd)
{int newfd = *(int *)fd;char buff[1024];while(1){int res = recv(newfd,buff,sizeof(buff),0);if(res == 0){printf("客户端下线\n");break;}strcat(buff,"霜之哀伤");printf("%s\n",buff);send(newfd,buff,sizeof(buff),0);bzero(buff,sizeof(buff));}//循环结束(客户端下线)子线程退出pthread_exit(NULL); 
}
int main(int argc, const char *argv[])
{//2、使用多线程基于TCP协议的并发执行,//一个服务器对应多个客户端实现通信实验。//1.创建套接字int oldfd = socket(AF_INET,SOCK_STREAM,0);if(oldfd == -1){perror("socket");return -1;}//绑定struct sockaddr_in aaa = {.sin_family = AF_INET,.sin_port = htons(PORT),.sin_addr.s_addr = inet_addr(IP)};if(bind(oldfd,(struct sockaddr *)&aaa,sizeof(aaa))==-1){perror("bind");return -1;}//监听if(listen(oldfd,20)==-1){perror("listen");return -1;}struct sockaddr_in client;int client_len = sizeof(client);pthread_t tid;int newfd;while(1){//接收新客户端连入请求newfd = accept(oldfd,(struct sockaddr *)&client,&client_len);if(newfd == -1){perror("accept");return -1;}//创建子线程与客户端通话if(pthread_create(&tid,NULL,fun,&newfd)==-1){perror("pthread_create");return -1;}}pthread_join(tid,NULL); 	//回收子线程资源close(newfd);close(oldfd);return 0;
}

客户端

#include <myhead.h>
#define IP "192.168.124.123"
#define PORT 8888int main(int argc, const char *argv[])
{//1.创建套接字int oldfd = socket(AF_INET,SOCK_STREAM,0);if(oldfd == -1){perror("socket");return -1;}//连接服务器struct sockaddr_in aaa = {.sin_family = AF_INET,.sin_port = htons(PORT),.sin_addr.s_addr = inet_addr(IP)};if(connect(oldfd,(struct sockaddr *)&aaa,sizeof(aaa))==-1){perror("connect");return -1;}//收发消息char buff[1024];while(1){fgets(buff,sizeof(buff),stdin);buff[strlen(buff)-1] = '\0';send(oldfd,buff,strlen(buff),0);if(strcmp(buff,"quit")==-1){printf("服务器退出成功\n");}bzero(buff,sizeof(buff));recv(oldfd,buff,strlen(buff),0); 		//阻塞接收服务器消息printf("服务器发来消息:%s\n",buff);}return 0;
}

笔记

1、对于套接字而言,在不同的层中,可以设置不同的属性,如端口号快速重用、超时时间、设置广播、加入多播组等等

2、关于网络属性,有两个函数,分别是 setsockopt、getsockopt

        #include <sys/types.h> /* See NOTES */

        #include <sys/socket.h>

        int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);

        功能:获取套接字某些选项的属性。

        参数1:套接字描述符

        参数2:要获取的层级

        参数3:要获取的操作名称

        参数4:获取的值为         0:表示禁用,

                                                非0表示启用。

        参数5:参数4的大小。

        返回值:成功返回0,失败返回-1,并置位错误码

        int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

        功能:设置套接字某些选项的属性。

        参数1:套接字描述符

        参数2:要设置的层级

        参数3:要设置的操作名称

        参数4:设置的值, 0:表示禁用,

                                        非0表示启用。

        参数5:参数4的大小。

        返回值:成功返回0,失败返回-1,并置位错误码

eg:获取当前端口号是否能快速复用属性:

        int n;

        int len = sizeof(n);

        getsockopt(oldfd,SOL_SOCKET,SO_REUSEADDR,&n,&len);

        如果n==0表示端口号快速复用未启动。

        如果n!=0表示端口号快速复用启动。

        eg:设置当前套接字端口号能快速复用

        int n =999;

        setsockopt(oldfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n));

        启动端口号快速复用功能。

#include <myhead.h>int main(int argc, const char *argv[])
{int oldfd = socket(AF_INET,SOCK_STREAM,0);int n;int len = sizeof(n);getsockopt(oldfd,SOL_SOCKET,SO_REUSEADDR,&n,&len);printf("端口号复用状态:%d\n",n);n = 1;setsockopt(oldfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n));printf("端口号修改为可复用状态后:%d\n",n);return 0;
}

2.单播

1>.单播发生在主机之间一对一的通信模式,交换机或者路由器只对数据进行转发,不做复制

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

3.广播

1>主机之间的一对多的通信模式,网络对其中的每一台主机发出的信息都进行复制并转发

2>所有主机都可以收到广播消息(无论你是否愿意接收),所以,广播是基于UDP通信模式

3> 广播地址:网络号 + 255

例如:主机地址为192.168.125.171 ---> 192.168.125.255

4> 广播消息是不能穿过路由器的,也就是说广播消息禁止在外网上进行传播,所以广播只能完成局域网内的多点通信

1、广播的发送端模型 ----> 类似于UDP的客户端

模式

1> socket 创建套接字

2> setsockopt 设置网络属性,允许广播

3> bind 非必须绑定(绑定的话每次发送端口都是固定的)

4> 填广播地址信息结构体

ip:填广播地址(192.168.125.255)

port:与接收端保持一致

5> sendto 发送消息

6> close 关闭套接字

#include <myhead.h>#define PORT 6666
#define IP "192.168.124.255"
int main(int argc, const char *argv[])
{//1、创建套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd==-1){perror("socket");return -1;}//2、设置允许广播int k = 999;if(setsockopt(oldfd,SOL_SOCKET,SO_BROADCAST,&k,sizeof(k))==-1){perror("setsockopt");return -1;}printf("允许广播设置成功\n");struct sockaddr_in broadcast = {.sin_family = AF_INET,.sin_port = htons(PORT),//发送到该端口.sin_addr.s_addr = inet_addr(IP)};char buff[1024];while(1){fgets(buff,sizeof(buff),stdin);sendto(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&broadcast,sizeof(broadcast));if(strcmp(buff,"quit")==0){printf("发送端退出\n");break;}}close(oldfd);return 0;
}

2、广播的接收端模型 ----> 类似于UDP的服务器端

模式

1> socket 创建套接字

2> 填充地址信息结构体

ip:广播地址(192.168.125.255)

port:与发送端保持一致

3> bind 绑定端口号与ip地址

4> recvfrom 接收消息

5> close 关闭套接字

发送源的负担:广播 > 组播 > 单播

特点:

1、广播地址选取broadcast对应的IP

2、端口号固定

3、发送端不需要绑定固定的IP和端口号,只需要向固定的IP和端口号(广播地址)发送信息即可,

不需要关注谁来接收。

4、接收端必须绑定IP和端口号(广播地址)

5、如果发送端绑定了IP和端口号之后,接收端就无法再次绑定,也无法接收信息。

4、组播(多播)

1、 组播也是实现主机之间一对多的通信模型,跟广播不同的是,组播发送的消息,只有加入多播组的成员才能收到,没有加入的就无法收到,不会占用柜台的网络带宽。

2> 组播也是使用UDP实现。

3> 组播地址:就是D类网络,224.0.0.0 -- 239.255.255.255

2、 组播的发送端模型 --->类似于UDP的客户端

模式

1> socket 创建套接字

2> bind 非必须绑定

3> 填充接收端地址信息结构体

ip:组播地址,与接收端保持一致(224.0.0.0 -- 239.255.255.255)

port:与接收端保持一致

4> sendto 发送组播消息

5> close 关闭套接字

组播发送端:

特点:

1、发送端发送给组播组IP和端口号。

2、发送端不需要绑定自己的IP和端口号,只需要发送到组播地址即可。

#include <myhead.h>
#define PORT 6666
#define IP "192.168.124.172"
int main(int argc, const char *argv[])
{//1、创建套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd==-1){perror("socket");return -1;}
#if 0//2、绑定struct sockaddr_in send = {.sin_family = AF_INET,.sin_port = htons(PORT),.sin_addr.s_addr = inet_addr(IP)};if(bind(oldfd,(struct sockaddr *)&send,sizeof(send))==-1){perror("bind");return -1;}
#endif//3、发送接收struct sockaddr_in group = {.sin_family = AF_INET,.sin_port = htons(8888),//组播端口号.sin_addr.s_addr = inet_addr("224.1.2.3")//组播IP地址};char buff[1024];while(1){fgets(buff,sizeof(buff),stdin);buff[strlen(buff)-1] = '\0';sendto(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&group,sizeof(group));}return 0;
}

3、组播的接收端模型 ---> 类似于UDP的服务器

1> socket 创建套接字

2> setsockopt 设置网络属性(加入多播组)

设置层级:IPPROTO_IP

设置属性:IP_ADD_MEMBERSHIP

struct ip_mreqn {

        struct in_addr imr_multiaddr; /* 组播IP*/

        struct in_addr imr_address; /* 本机IP*/

        int imr_ifindex; /* 网卡索引 */ };

3> 填充地址信息结构体然后bind

ip:组播IP,与发送端保持一致

port :与发送端保持一致

4> 定义发送方结构体,接收发送方信息

5> recvfrom 接收消息

6> close 关闭套接字

特点:

1、设置允许加入组播组(发送端的IP),设置加入组播组时需要(组播组IP,自己的IP,自己网卡ens33的索引号一般都是2)

2、查找自己网卡的索引号:ip addr show或者ip ad。

3、绑定时绑定的是组播组IP和发送端IP保持一致。

4、接收端也可以选择不接收发送方信息,recvfron最后两个参数填NULL即可。

#include <myhead.h>
#define ZIP "224.1.2.3"
#define IP "192.168.60.66"
#define PORT 7777
int main(int argc, const char *argv[])
{//1、创建基于UDP的套接字int oldfd = socket(AF_INET,SOCK_DGRAM,0);if(oldfd==-1){perror("socket");return -1;}//2、设置允许加入组播组struct ip_mreqn recv = {.imr_multiaddr.s_addr = inet_addr(ZIP),//组播组IP.imr_address.s_addr = inet_addr(IP),//本机IP.imr_ifindex = 2 //ens33网卡索引号};if(setsockopt(oldfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&recv,sizeof(recv))==-1){perror("setsockopt");return -1;}//3、绑定struct sockaddr_in recv2 = {.sin_family = AF_INET,.sin_port = htons(PORT),.sin_addr.s_addr = inet_addr(ZIP)//绑定组播组IP};if(bind(oldfd,(struct sockaddr *)&recv2,sizeof(recv2))==-1){perror("bind");return -1;}//4、接收信息struct sockaddr_in send;socklen_t send_len = sizeof(send);char buff[1024];while(1){recvfrom(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&send,&send_len);//recvfrom(oldfd,buff,sizeof(buff),0,NULL,NULL);不接收发送方的信息printf("接收到%s发送来的信息:%s\n",inet_ntoa(send.sin_addr),buff);if(strcmp(buff,"quit")==0){printf("接收端也退出\n");break;}}close(oldfd);return 0;
}

思维导图

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

点进CSS选择器

CSS 1.直接在标签的style属性进行设置(行内式) //写在数据单元格td标签内的stytle&#xff0c;设置color颜色和font-size字体大小&#xff1b; <td rowspan"3" style"color: red;font-size: 12px;">Web技术与应用</td> 2.写在head标签中的…

UE5材质节点BumpOffset

BumpOffset 凹凸偏移&#xff0c;可以让材质显示视差偏移的效果 Coordinate是UV&#xff0c;Height是凹凸偏移高度&#xff0c;HeightRatioInput用来控制高度比

仙盟系统开发——启动app失败

var 返回 仙盟使者.Cyber_CallApp(VOAPP, 命令, 携带);

LabVIEW声波谐振管自动化测量系统

开发了一种基于LabVIEW的声波谐振管自动化测量系统。该系统利用LabVIEW的强大功能&#xff0c;实现了对声波谐振频率的精确测量&#xff0c;提高了实验数据的采集效率和准确性。系统主要应用于物理教学和科研中&#xff0c;用于研究声波在谐振管中的传播特性。 项目背景 传统的…

学习笔记:使用 pandas 和 Seaborn 绘制柱状图

学习笔记&#xff1a;使用 pandas 和 Seaborn 绘制柱状图 前言 今天在使用 pandas 对数据进行处理并在 Python 中绘制可视化图表时&#xff0c;遇到了一些关于字体设置和 Seaborn 主题覆盖的小问题。这里将学习到的方法和注意事项做个总结&#xff0c;以便之后的项目中可以快…

【Linux】进程间通信-> 共享内存

共享内存原理 在C语言/C中&#xff0c;malloc也可以在物理内存申请空间&#xff0c;将申请的物理内存空间通过页表映射到进程地址空间&#xff0c;将内存空间的起始地址&#xff08;虚拟地址&#xff09;返回&#xff0c;进而进程可以使用虚拟地址通过页表映射到物理内存的方式…

【yolov5】实现FPS游戏人物检测,并定位到矩形框上中部分,实现自瞄

介绍 本人机器学习小白&#xff0c;通过语言大模型百度进行搜索&#xff0c;磕磕绊绊的实现了初步效果&#xff0c;能有一些锁头效果&#xff0c;但识别速度不是非常快&#xff0c;且没有做敌友区分&#xff0c;效果不是非常的理想&#xff0c;但在4399小游戏中爽一下还是可以…

【Maven】Maven打包机制详解

Maven打包的类型&#xff1f; 以下是几种常见的打包形式&#xff1a; 1、jar (Java Archive) 用途&#xff1a;用于包含 Java 类文件和其他资源&#xff08;如属性文件、配置文件等&#xff09;的库项目。特点&#xff1a; 可以被其他项目作为依赖引用。适合创建独立的应用程…

MySQLOCP考试过了,题库很稳,经验分享。

前几天&#xff0c;本人参加了Oracle认证 MySQLOCP工程师认证考试 &#xff0c;先说下考这个证书的初衷&#xff1a; 1、首先本人是从事数据库运维的&#xff0c;今年开始单位逐步要求DBA持证上岗。 2、本人的工作是涉及数据库维护&#xff0c;对这块的内容比较熟悉&#xff…

MySQL数据导出导出的三种办法(1316)

数据导入导出 基本概述 目前常用的有3中数据导入与导出方法&#xff1a; 使用mysqldump工具&#xff1a; 优点&#xff1a; 简单易用&#xff0c;只需一条命令即可完成数据导出。可以导出表结构和数据&#xff0c;方便完整备份。支持过滤条件&#xff0c;可以选择导出部分数据…

Go 协程池 Gopool VS ants 原理解析

写过高并发的都知道&#xff0c;控制协程数量是问题的关键&#xff0c;如何高效利用协程&#xff0c;本文将介绍gopool和ants两个广泛应用的协程池&#xff0c;通过本文你可以了解到&#xff1a; 1. 实现原理 2. 使用方法 3. 区别 背景 虽然通过go func()即可轻量级实现并发&…

无人机无法返航紧急处理方式!

一、检查飞行环境 了解禁飞原因和规定&#xff1a;首先&#xff0c;需要了解所在地区的无人机飞行规定&#xff0c;确认是否存在禁飞区或限飞区。如果处于禁飞区&#xff0c;应遵守相关规定&#xff0c;不要强行飞行。 检查天气情况&#xff1a;恶劣的天气条件&#xff08;如…

NLP论文速读(NeurIPS 2024)|BERT作为生成式上下文学习者BERTs are Generative In-Context Learners

论文速读|BERTs are Generative In-Context Learners 论文信息&#xff1a; 简介&#xff1a; 本文探讨了在自然语言处理&#xff08;NLP&#xff09;领域中&#xff0c;上下文学习&#xff08;in-context learning&#xff09;的能力&#xff0c;这通常与因果语言模型&#x…

vue3<script setup>中使用Swiper

swiper网址 Swiper中文网-轮播图幻灯片js插件,H5页面前端开发 Swiper - The Most Modern Mobile Touch Slider 安装 Swiper npm安装&#xff1a; npm install swiper yarn安装&#xff1a; yarn add swiper 导入带有所有模块&#xff08;捆绑包&#xff09;的 Swiper //…

今日收获(C语言)

一.文件的打开 有这样一个结构体&#xff0c;它内部是文件信息区&#xff0c;文件信息区中的变化可以影响到硬盘中的数据。这个结构体的名字是FILE。我们如果想要写代码对文件进行各种操作&#xff0c;就需要一个指向文件信息区的指针&#xff0c;这个指针的类型是FILE*&#…

node.js卸载并重新安装(超详细图文步骤)

卸载node.js 重新安装nodejs 一、卸载 1、首先进入控制面板卸载程序 2、卸载后 到文件夹中进行进一步的删除 删除上述的几个文件夹 每个人可能不一样&#xff0c;总之是找到自己的nodejs安装路径&#xff0c;下面是我的 ①删除C:UsersAdminAppDataRoaming路径下的npm相关文件…

仓颉编程语言:编程世界的 “文化瑰宝”

我的个人主页 在当今编程领域百花齐放的时代&#xff0c;各种编程语言争奇斗艳&#xff0c;服务于不同的应用场景和开发者群体。然而&#xff0c;有这样一种编程语言&#xff0c;它承载着独特的文化内涵&#xff0c;宛如编程世界里一颗熠熠生辉的“文化瑰宝”&#xff0c;那就…

Android使用JAVA调用JNI原生C++方法

1.native-lib.cpp为要生成so库的源码文件 2.JNI函数声明说明 NewStringUTF函数会返回jstring JNI函数声明规则 3.JAVA中声明及调用JNI函数 声明&#xff1a; 调用

DAY178内网渗透之内网对抗:横向移动篇入口差异切换上线IPC管道ATSC任务Impacket套件UI插件

1.内网横向移动 1、横向移动篇-入口点分析-域内域外打点 2、横向移动篇-IPC利用-连接通讯&计划任务, 3、横向移动篇-IPC利用-命令模式&工具套件 1.1 横向移动入口知识点 收集到域内用户和凭据后&#xff0c;为后续利用各种协议密码喷射通讯上线提供条件&#xff0c;…

宠物行业的出路:在爱与陪伴中寻找增长新机遇

在当下的消费市场中&#xff0c;如果说有什么领域能够逆势而上&#xff0c;宠物行业无疑是一个亮点。当人们越来越注重生活品质和精神寄托时&#xff0c;宠物成为了许多人的重要伴侣。它们不仅仅是家庭的一员&#xff0c;更是情感的寄托和生活的调剂。然而&#xff0c;随着行业…