嵌入式学习第二十五天!(网络的概念、UDP编程)

网络:

    可以用来:数据传输数据共享

1. 网络协议模型:

    1. OSI协议模型:

应用层实际收发的数据
表示层发送的数据是否加密
会话层是否建立会话连接
传输层数据传输的方式(数据包,流式)
网络层数据的路由(如何从一个局域网到达另一个局域网)
数据链路层局域网下如何通信
物理层物理介质的连接

      2. TCP/IP协议模型:

应用层传输的数据
传输层传输的方式
网络层数据如何从一个台主机到达另一台主机
网络接口层物理介质的连接
        1. 应用层:

               例如有:HTTP      超文本传输协议

                              HTTPS   

                              FTP        文件传输协议

                              TFTP      简单文本传输协议

                              SMTP     邮件传输协议

                              MQTT

                              TELNET

                              ...

        2. 传输层:

              UDP:用户数据报协议

                    特点:1. 实现机制简单

                               2. 资源开销小

                               3. 不安全不可靠

              TCP:传输控制协议

                      特点:1. 实现机制复杂

                                 2. 资源开销大

                                 3. 安全可靠

        3. 网络层:

              IPv4

              IP地址:唯一网络中一台主机的标号

              IP地址:网络位 + 主机位

              子网掩码:用来标识IP地址的网络位和主机位

                                子网掩码是1的部分表示IP地址的网络位

                                子网掩码是0的部分表示IP地址的主机位

                网段号:网络位不变,主机位全位0,表示网段号

                广播地址:网络位不变,主机位全为1,表示广播地址

                IP地址类型:

                A类:

                        1.0.0.0  -  126.255.255.255

                        子网掩码:255.0.0.0

                        管理超大规模网络

                        私有IP地址:10.0.0.0  -  10.255.255.255

                B类:

                        128.0.0.0  -  191.255.255.255

                        子网掩码:255.255.0.0

                        管理大中规模型网络

                        私有IP地址:172.16.0.0  -  172.31.255.255

                C类:

                        192.0.0.0  -  223.255.255.255

                        子网掩码:255.255.255.0

                        管理中小规模型网络

                        私有IP地址:192.168.0.0  -  192.168.255.255

                D类:

                        224.0.0.0  -  239.0.0.0

                        用于组播

                E类:

                        240.0.0.0  -  255.255.255.255

                        用于实验

        4. UDP编程:

            socket套接字(全双工)编程:

            发端:socket  ->  sendto  ->  close

            收端:socket  ->  bind  ->  recvfrom  ->  close

            1. 发端
                1. socket:
int socket(int domain, int type, int protocol);

                    功能:创建一个用来通信的文件描述符

                    参数:

                        domain:使用的协议族 AF_INET(IPv4协议族)

                        type:套接字类型

                                SOCK_STREAM:流式套接字

                                SOCK_DGRAM:数据报套接字

                                SOCK_RAW:原始套接字

                        protocol:协议

                                默认为0;

                    返回值:

                        成功返回文件描述符
                        失败返回-1

                2. sendto:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

                    功能:利用套接字向指定地址发送数据信息

                    参数:

                        sockfd:套接字文件描述符

                        buf:发送数据空间首地址

                        len:发送数据的长度

                        flags:属性默认为0

                        dest_addr:目的地址信息存放的空间首地址

                        addrlen:目的地址的长度

struct sockaddr_in {sa_family_t    sin_family; /* address family: AF_INET */in_port_t      sin_port;   /* port in network byte order */struct in_addr sin_addr;   /* internet address */
};/* Internet address. */
struct in_addr {uint32_t       s_addr;     /* address in network byte order */
};

                    返回值:

                        成功返回实际发送字节数
                        失败返回-1

                3. inet_addr:
in_addr_t inet_addr(const char *cp);

                    功能:将字符串IP地址转换为内存中的IP地址

                4. htons:
uint16_t htons(uint16_t hostshort);

                    功能:将本地字节序转换为网络的大端字节序

            练习:

                1. 编写程序实现从终端接收字符串发送给windows软件调试助手,并接收软件助手的回复,显示在终端屏幕上

#include "head.h"int main(void)
{int sockfd = 0;ssize_t nsize = 0;char tmpbuff[1024] = {0};struct sockaddr_in recvaddr;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1){perror("fail to socket");return -1;}gets(tmpbuff);recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(50000);recvaddr.sin_addr.s_addr = inet_addr("192.168.1.162");bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(&recvaddr));nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if(nsize == -1){perror("fail to sendto");return -1;}printf("成功发送 %ld 字节!\n", nsize);memset(tmpbuff, 0, sizeof(tmpbuff));nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, (struct sockaddr *)&recvaddr, (socklen_t *)sizeof(&recvaddr));printf("%s\n",tmpbuff);close(sockfd);return 0;
}
             2. 收端
                1. recvfrom:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

                    功能:从套接字中接收数据

                    参数:

                        sockfd:套接字文件描述符

                        buf:存放数据空间首地址

                        flags:属性,默认为0

                        src_addr:存放IP地址信息的空间首地址

                        addlen:存放接收到IP地址大小空间的首地址

                    返回值:

                        成功返回实际接收字节数
                        失败返回-1 

                2. 修改虚拟机到桥接模式:

                    点击“虚拟机”

                    点击“设置”

                    点击“网络适配器”

                    选择“桥接模式”

                    点击“确定”

                3. 将网卡桥接到无线网卡:

                    点击“编辑”

                    点击“虚拟网络编辑器”

                    点击“更改设置”

                4. 在Ubuntu中重启网络服务:
sudo /etc/init.d/networking restart 
                5. 通过ifconfig查看虚拟机IP地址
                6. bind:
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

                    功能:在套接字上绑定一个IP地址和端口号

                    参数:

                        sockfd:套接字文件描述符

                        addr:绑定IP地址空间首地址

                        addrlen:绑定IP地址的长度

                    返回值:

                        成功返回0 
                        失败返回-1 

            3. UDP需要注意的细节点:

                1. UDP是无连接,发端退出,收端没有任何影响

                2. UDP发送数据上限,最好不要超过1500个字节

                3. UDP是不安全不可靠的,连续且快速的传输数据容易产生数据丢失

            4. wireshark

                可以通过wireshark抓包工具来查看收发的数据

                操作流程:

                    1. 打开wireshark:

sudo wireshark

                    2. 选择抓取数据包的网卡:any

                    3. 执行通信的代码

                    4. 停止通信

                    5. 设定过滤条件

                        ip.addr == IP地址  :通过IP地址查找

                        udp                        :通过传输方式udp查找

                        tcp                         :通过传输方式tcp查找

                        udp.port == 端口号:通过端口号查找

            5. UDP包头长度:8个字节

                源端口号(2个字节)

                目的端口号(2个字节)

                长度(2个字节)

                检验和(2个字节)

            练习:

                要求在不同主机中编写两个程序,实现全双工聊天功能

                1. 进入软件后接收当前用户的昵称

                2. 显示的格式为对方用户昵称 (对方IP:对方端口) > 接收到的内容

                3. 用户输入“.quit”退出聊天

                4. 网络通信时收发结构体

struct person 
{char name[32];char text[512];
};
#include "head.h"int sockfd = 0;
ssize_t nsize = 0;
struct sockaddr_in tmpaddr;
struct sockaddr_in sendaddr;
socklen_t addrlen = sizeof(tmpaddr);struct person
{char name[32];char text[512];
};pthread_t tid_recv;
pthread_t tid_send;void *RecvInfo(void *arg)
{struct person user;while(1){memset(&user, 0, sizeof(user));nsize = recvfrom(sockfd, &user, sizeof(user), 0, (struct sockaddr *)&tmpaddr, &addrlen);if(nsize == -1){perror("fail to recvfrom");return NULL;}printf("%s %s : %d > %s\n", user.name, inet_ntoa(tmpaddr.sin_addr), ntohs(tmpaddr.sin_port), user.text);if(!strcmp(user.text, ".quit")){break;}}pthread_cancel(tid_send);return NULL;
}void *SendInfo(void *arg)
{struct person user;while(1){memset(&user, 0, sizeof(user));scanf("%s", user.name);scanf("%s", user.text);nsize = sendto(sockfd, &user, sizeof(user), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr));if(nsize == -1){perror("fail to sendto");return NULL;}printf("success send %ld byte\n", nsize);if(!strcmp(user.text, ".quit")){break;}}pthread_cancel(tid_recv);return NULL;
}int main(void)
{struct sockaddr_in recvaddr;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1){perror("fail to socket");return -1;}recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(30000);recvaddr.sin_addr.s_addr = inet_addr("192.168.1.153");bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));sendaddr.sin_family = AF_INET;sendaddr.sin_port = htons(30000);sendaddr.sin_addr.s_addr = inet_addr("192.168.1.152");pthread_create(&tid_recv, NULL, RecvInfo, NULL);pthread_create(&tid_send, NULL, SendInfo, NULL);pthread_join(tid_recv, NULL);pthread_join(tid_send, NULL);close(sockfd);return 0;}
        5. UDP项目练习:

        题目:基于UDP实现直播间聊天的功能:

        需求:

                软件划分为用户客户端和主播服务端两个软件client.c和server.c

                用户客户端负责:

                        1.接收用户的昵称
                        2.接收用户输入的信息,能够将信息发送给服务端
                        3.接收服务端回复的数据信息,并完成显示

                主播服务端负责:

                        1.对所有加入直播间的用户的IP地址和端口实现管理(加入、退出)
                        2.当有新的客户端加入时,能够向所有客户端提示:"欢迎 XXX 用户进入直播间"
                        3.当有客户端退出时,能够向所有客户端提示:"XXX 离开直播间"
                        4.能够实现客户端聊天内容的转发,当某个客户端发送聊天信息时,能够将该信息转给除了该用户之外聊天室内所有其余客户端用户

client.c

#include "head.h"int sockfd = 0;
char name[32];
struct sockaddr_in recvaddr;
pthread_t tid_send;
pthread_t tid_recv;void *SendMsg(void *arg)
{struct msgbuf sendmsg;ssize_t nsize = 0;while(1){memset(&sendmsg, 0, sizeof(sendmsg)); sendmsg.type = USER_TYPE_CHAT;sprintf(sendmsg.name, "%s", name);gets(sendmsg.text);if(strcmp(sendmsg.text,".quit") == 0){sendmsg.type = USER_TYPE_OUT;}nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if(nsize == -1){perror("fail to sendto");return NULL;}if(sendmsg.type == USER_TYPE_OUT){break;}}pthread_cancel(tid_recv);return NULL;
}void *RecvMsg(void *arg)
{struct msgbuf recvmsg;ssize_t nsize = 0;while(1){nsize = recvfrom(sockfd, &recvmsg, sizeof(recvmsg), 0, NULL, NULL);if(nsize == -1){perror("fail to recvfrom");return NULL;}if(recvmsg.type == USER_TYPE_CHAT){printf("%s>%s\n", recvmsg.name, recvmsg.text);}if(recvmsg.type == USER_TYPE_OUT){break;}}return NULL;
}int main(void)
{ssize_t nsize = 0;struct msgbuf sendmsg; sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1){perror("fail to socket");return -1;}printf("请输入你的名字:\n");gets(name);memset(&sendmsg, 0, sizeof(sendmsg));sendmsg.type = USER_TYPE_INT;sprintf(sendmsg.name, "%s", name);recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(SERVER_PORT);recvaddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);nsize = sendto(sockfd, &sendmsg, sizeof(sendmsg), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if(nsize == -1){perror("fail to sendto");return -1;}pthread_create(&tid_send, NULL, SendMsg, NULL);pthread_create(&tid_recv, NULL, RecvMsg, NULL);pthread_join(tid_send, NULL);pthread_join(tid_recv, NULL);close(sockfd);
}

server.c

#include "head.h"int main(void)
{int sockfd = 0;ssize_t nsize = 0;ssize_t size = 0;struct sockaddr_in serveraddr;struct address useraddr[100];struct sockaddr_in userinfo;socklen_t addrlen = 0;addrlen = sizeof(userinfo);struct msgbuf recvuser;int i = 0;sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd == -1){perror("fail to socket");return -1;}serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(SERVER_PORT);serveraddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));memset(useraddr, 0, sizeof(useraddr));while(1){memset(&recvuser, 0, sizeof(recvuser));memset(&userinfo, 0, sizeof(userinfo));nsize = recvfrom(sockfd, &recvuser, sizeof(recvuser), 0, (struct sockaddr *)&userinfo, &addrlen);if(nsize == -1){return -1;}if(recvuser.type == USER_TYPE_INT){for(i = 0; i < 100; i++){if(useraddr[i].mark == 1){continue;}else if(useraddr[i].mark == 0){useraddr[i].mark = 1;useraddr[i].cltaddr.sin_family = AF_INET;useraddr[i].cltaddr.sin_port = userinfo.sin_port;useraddr[i].cltaddr.sin_addr.s_addr = userinfo.sin_addr.s_addr;printf("欢迎用户:%s来到直播间!\n", recvuser.name);break;}}}else if(recvuser.type == USER_TYPE_OUT){for(i = 0; i < 100; i++){if(memcmp(&useraddr[i].cltaddr, &userinfo, sizeof(userinfo)) == 0){useraddr[i].mark = 0;printf("用户:%s离开直播间!\n", recvuser.name);}}}else if(recvuser.type == USER_TYPE_CHAT){printf("%s(%s:%d)>%s\n", recvuser.name, inet_ntoa(userinfo.sin_addr), ntohs(userinfo.sin_port), recvuser.text);for(i = 0; i < 100; i++){if(useraddr[i].mark != 0){size = sendto(sockfd, &recvuser, sizeof(recvuser), 0, (struct sockaddr *)&useraddr[i].cltaddr, sizeof(useraddr[i].cltaddr));if(size == -1){perror("fail to sendto");return -1;}}}}}	close(sockfd);return 0;
}

在这里head.h中定义了两个结构体,已经定义了客户发过来的状态

#ifndef _HEAD_H_
#define _HEAD_H_#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>struct msgbuf
{int type;char name[32];char text[512];
};struct address
{struct sockaddr_in cltaddr;int mark;
};#define USER_TYPE_INT  100
#define USER_TYPE_OUT   200
#define USER_TYPE_CHAT  300#define SERVER_ADDR  "192.168.1.162"
#define SERVER_PORT  5000#endif

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

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

相关文章

吴恩达深度学习笔记:神经网络的编程基础2.1-2.3

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第二周&#xff1a;神经网络的编程基础 (Basics of Neural Network programming)2.1 二分类(Binary Classification)2.2 逻辑回归(Logistic Regression) 第一门课&#xff1a;神经网络和深度学…

基于YOLOv5的无人机视角水稻杂草识别检测

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍了无人机视角水稻杂草识别检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析。 博主简介 AI小怪兽&#xff0c;YOLO骨灰级玩家&#xff0c;1&#xff09;YOLOv5、v7、v8优化创新&#xff0c;轻松涨点…

Github 2024-03-08 Java开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-08统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9C++项目1非开发语言项目1《Hello 算法》:动画图解、一键运行的数据结构与算法教程 创建周期:476 天协议类型:OtherStar数量:63556…

网络原理初识(2)

目录 一、协议分层 1、分层的作用 2、OSI七层模型 3、TCP / IP五层&#xff08;或四层&#xff09;模型 4、网络设备所在分层 5、网络分层对应 二、封装和分用 发送过程&#xff08;封装&#xff09; 1、应用层(应用程序) QQ 2、输入层 3、网络层 4、数据链路层 5、物理…

金融行业专题|基金超融合架构转型与场景探索合集(2023版)

更新内容 更新 SmartX 超融合在基金行业的覆盖范围、部署规模与应用场景。更新信创云资源池、关键业务系统性能优化等场景实践。更多超融合金融核心生产业务场景实践&#xff0c;欢迎下载阅读电子书《金融核心生产业务场景探索文章合集》。 随着数字化经济的蓬勃发展&#xf…

记一次Flink任务无限期INITIALIZING排查过程

1.前言 环境&#xff1a;Flink-1.16.1&#xff0c;部署模式&#xff1a;Flink On YARN&#xff0c;现象&#xff1a;Flink程序能正常提交到 YARN&#xff0c;Job状态是 RUNNING&#xff0c;而 Task状态一直处于 INITIALIZING&#xff0c;如下图&#xff1a; 通过界面可以看到…

ue4.27 发现 getRandomReachedLocation 返回 false

把这个玩意儿删掉&#xff0c;重启工程&#xff0c;即可 如果还不行 保证运动物体在 volum 内部&#xff0c;也就是绿色范围内确保 project setting 里面的 navigation system 中 auto create navigation data 是打开的(看到过博客说关掉&#xff0c;不知道为啥) 如果还不行&…

智奇科技工业 Linux 屏更新开机logo

智奇科技工业 Linux 屏更新开机logo 简介制作logo.img文件1、转换格式得到logo.bmp2、使用Linux命令生成img文件 制作rootfs.img文件替换rootfs.img中的logo 生成update.img固件附件 简介 智奇科技的 Linux 屏刷开机logo必须刷img镜像文件&#xff0c;比较复杂。 制作logo.i…

深入浅出(二)MVVM

MVVM 1. 简介2. 示例 1. 简介 2. 示例 示例下载地址&#xff1a;https://download.csdn.net/download/qq_43572400/88925141 创建C# WPF应用(.NET Framework)工程&#xff0c;WpfApp1 添加程序集 GalaSoft.MvvmLight 创建ViewModel文件夹&#xff0c;并创建MainWindowV…

通过对话式人工智能打破语言障碍

「AI突破语言障碍」智能人工智能如何让全球交流无障碍 在当今互联的世界中&#xff0c;跨越语言界限进行交流的能力比以往任何时候都更加重要。 对话式人工智能&#xff08;包括聊天机器人和语音助手等技术&#xff09;在打破这些语言障碍方面发挥着关键作用。 在这篇博文中&am…

简站wordpress主题看上去差不多 实际大不一样

有人说简站wordpress主题&#xff0c;都差不多嘛。我表示无语。表面看上去是差不多的&#xff0c;实际的细节是不一样的。 下面以编号&#xff1a;JZP4431和编号&#xff1a;JZP4878这两个主题为例子来讲一下&#xff0c;简站wordpress主题&#xff0c;在细节方面的不一样之处…

【观察】华为:加速行业智能化,正在“走深向实”

毫无疑问&#xff0c;犹如历史上蒸汽机、电力、计算机和互联网等通用技术一样&#xff0c;近20年来&#xff0c;人工智能正以史无前例的速度和深度改变着人类社会和经济&#xff0c;为释放人类创造力和行业生产力&#xff0c;以及促进经济增长都提供了巨大的机会。 根据高盛报告…

字符串函数和内存函数

文章目录 字符串函数strlen函数模拟实现 strcpy函数模拟实现 strcat函数使用模拟实现 strcmp函数使用模拟实现 strncpy函数使用模拟实现 strstr函数使用模拟实现 strtok函数使用 strerror函数使用 内存函数memset函数使用memcmp函数memcpy函数使用模拟实现 memmove函数使用模拟…

【深度优先】【图论】【C++算法】2045. 到达目的地的第二短时间

作者推荐 视频算法专题 LeetCode2045. 到达目的地的第二短时间 城市用一个 双向连通 图表示&#xff0c;图中有 n 个节点&#xff0c;从 1 到 n 编号&#xff08;包含 1 和 n&#xff09;。图中的边用一个二维整数数组 edges 表示&#xff0c;其中每个 edges[i] [ui, vi] 表…

HCIP---IS-IS协议

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.IS-IS协议概述 IS-IS是一种基于链路状态的内部网关协议&#xff08;IGP&#xff09;&#xff0c;它使用最短路径优先算法&#xff08;SPF或Dijkstra&#xff09;进行路由计算。这种协议在自治…

[密码学]入门篇——加密方式

一、概述 加密方法主要分为两大类&#xff1a; 单钥加密&#xff08;private key cryptography&#xff09;&#xff1a;加密和解密过程都用同一套密码双钥加密&#xff08;public key cryptography&#xff09;&#xff1a;加密和解密过程用的是两套密码 历史上&#xff0c…

u盘里文件损坏无法打开怎么恢复?这样操作更简单

U盘已经成为我们传输和存储数据的重要工具。然而有时候我们可能会遇到U盘里的文件损坏无法识别的情况&#xff0c;这无疑给我们的工作和学习带来了不小的困扰。 那么面对这种情况应该如何应对呢&#xff1f;本文将为你介绍个实用的恢复方法&#xff0c;帮助你轻松解决U盘文件损…

【洛谷 P8662】[蓝桥杯 2018 省 AB] 全球变暖 题解(深度优先搜索+位集合)

[蓝桥杯 2018 省 AB] 全球变暖 题目描述 你有一张某海域 N N N \times N NN 像素的照片&#xff0c;. 表示海洋、 # 表示陆地&#xff0c;如下所示&#xff1a; ....... .##.... .##.... ....##. ..####. ...###. .......其中 “上下左右” 四个方向上连在一起的一片陆地组…

机器学习-面经

经历了2023年的秋招&#xff0c;现在也已经入职半年了&#xff0c;空闲时间将面试中可能遇到的机器学习问题整理了一下&#xff0c;可能答案也会有错误的&#xff0c;希望大家能指出&#xff01;另外&#xff0c;不论是实习&#xff0c;还是校招&#xff0c;都祝福大家能够拿到…