通信原理课设(gec6818) 006:网络编程
目录
1、概念
2、通信
3、通信基本流程
TCP:
UDP:
4、函数
I 创建套接字
II 绑定地址
III 字节序转换
IV 地址转换
V 监听
VI accept
VII connect
VIII 从套接字接收信息
IX 从套接字发送消息
X 关闭套接字
5、网络配置
1、确保你的网卡里面有两个虚拟网卡,你的有线网卡的型号也在这里面看 在更改适配器里面看是否有VMnet1 VMnet8
2、配置电脑的有线网卡ip
3、配置ubuntu的ip
4、配置开发板的ip
6、练习:实现简单的网络编程,客户端和服务器端可以实现通信
1、概念
如果两个计算机想要通信,那么这两台计算机必须在同一个局域网在一个局域网之内,如果想要进行通信,那么这两者都必须要有唯一一个ID --- IP地址
现在我们用的是IPV4 -> 4个字节来表示一台主机,由于这个IPV4资源有限,所以现在扩充到了IPV6
IPV4四个字节,如果一个局域网内将所有的ip分完,那么可以分配给2 ^ 32 个主机
在世界上面来说,局域网的数量也不少,在互联网上面是不同的局域网之内的用户在进行通信,因此我们去找到另外一台主机的时候,除了去区分这个主机以外,还需要区分局域网(局域网+主机)
因此我们的ip地址分为两个部分:网络号 + 主机号
网络号:用来标识我们的局域网
主机号:用来标识我们局域网里面的主机
对于一个ip地址来说,我需要去区分哪些是网络号,哪些是主机号
我们通过4个字节,前面用全部的1构成,后面用全部的0构成
只要我们设置的足够好,那么我就可以使用这些1和0来区分,你的ip地址上面**哪些是网络号,哪些是主机号,这个东西我们就叫子网掩码。
举个例子:
一个点分式ip地址为:192.168.31.249
子网掩码为: 255.255.255.0
---------------->网络号:192.168.31
---------------->主机号:249(注意:主机号一般不为0和255)
11111111 11111111 11111111 11111111 -> 全是网络号,没有主机,因此没有什么作用
00000000 00000000 00000000 00000000 -> 全部是主机,没有网络,可以的,这是世界最大的网
注意:掩码的左边部分一定要是全为1且中间不能有0出现
比方说将255.255.248.0转为二进制是 11111111.11111111.11111000.00000000,可以看到左边都是1,在1的中间没有0出现(0都在1的右边),这样就是一个有效的掩码。我们再来看254.255.248.0,转成二进制是 11111110.11111111.11111000.00000000,这不是一个正确有效的掩码,因为在1中间有一个0的存在。
由于一台电脑里面可能运行多个网络程序,但是他们对应的网卡都是一个,因此ip地址都是共用的,因此我们必须还要有一个机制去区分网络程序 ----- 端口,端口号用于去区分网络程序的,现在是2个字节
0 ~ 1023 -> 知名端口
1024 ~ 49151 -> 注册端口,随便用,只要不冲突就行了
后面一节是私有端口,暂时不要用
所以:网络程序=ip+端口
网络编程都是对应两端的
1 服务端 --- 服务器
2 客户端 --- 客户端的应用程序
客户端发起服务请求,服务器响应这个请求
2、通信
我们的通信有两种
1 TCP --- 面向连接的,可靠通信,保证数据的无丢失无失序,有重发机制,也就是数据没有成功到达,会重发
2 UDP --- 面向无连接的,通信是不可靠的,但是效率要高于TCP,大量的实时不可靠通信我们就用UDP
3、通信基本流程
TCP:
服务端 -> tcp_server.c
1. 创建套接字 ---- 什么都是文件,因此你的网络通信也是一个文件,这个文件我们就叫套接字, 是一个特殊的文件描述符 sockfd
2. 我们需要将服务器的IP地址绑定到套接字
3. 监听连接 ---- 创建一个监听队列.建立5个10个可以了
4. 循环等待客户端的连接,如果没有连接则等待,如果有连接则返回一个连接套接字
5. 和客户端进行正常收发
6. 关闭套接字
客户端 -> tcp_client.c
1. 创建套接字
2. 准备服务器的ip地址,准备连接
3. 连接服务器
4. 和服务器进行正常收发
5. 关闭套接字
UDP:
服务端 -> udp_server.c
1. 创建套接字
2. 绑定地址
3. 等待客户端给你发送信息
如果等待了客户端的信息,服务器会知道客户端的地址
根据刚刚得到的客户端的地址给客户端发送信息即可
4. 最后弄完了关闭套接字
客户端 udp_client.c
1. 创建套接字
2. 准备服务器地址,准备给服务器发送信息
3. 给服务器发送信息,然后可根据我们自己的项目逻辑来进行收发
4. 最后弄完了关闭套接字
4、函数
I 创建套接字
NAMEsocket - create an endpoint for communication创建一个套接字SYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int socket(int domain, int type, int protocol);
参数解释:
domain:传输层的协议
AF_UNIX UNIX协议域,可以实现进程间通信
AF_INET IPV4
AF_INET6 IPV6
....
type:你采用那种协议进程数据传输
SOCK_STREAM 面向连接 -> TCP
SOCK_DGRAM 面向无连接 -> UDP
protocol:私有协议 我们直接写0 表示一个不知名的协议
返回值: 成功返回一个套接字,类似于文件描述符 失败返回-1,同时errno被设置
II 绑定地址
NAME 名称bind - 将一个名字和一个套接字绑定到一起(赋一个名字给一个套接字)SYNOPSIS 概述#include <sys/types.h>#include <sys/socket.h>将 my_addr这个地址绑定到sockfd这个套接字上面去int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
参数解释:
sockfd:套接字 你要绑定到这个套接字上面来
my_addr:我们的地址 struct sockaddr这个地址是一个公版 根据需求我们自己要选用正确的类型,在这里我们应该选用面向网络的struct sockaddr_instruct sockaddr_in { //这个类型是面向网络的 因此我们需要选用这个类型sa_family_t sin_family; /* 地址族: AF_INET */ u_int16_t sin_port; /* 按网络字节次序的端口 */struct in_addr sin_addr; /* internet地址 */};
sin_family:这里就是socket第一个参数的填法
sin_port :端口号 在注册端口里面选用一个即可
sin_addr : ip地址
/* Internet地址. */
struct in_addr {
u_int32_t s_addr; /* 按网络字节次序的地址 */ };s_addr:可以看到ip是一个整数,和之前讲的点分式(如192.168.31.249) 不同,因为点分式只是为了更加方便人看,192.168.31.249转换成 整数就是0xC0A81FF9。那什么又是网络字节序呢?这与大端小端 字节序有关:
①大端字节序(Big Endian):最高有效位存于最低内存地址处, 最低有效位存于最高内存处;
②小端字节序(Little Endian):最高有效位存于最高内存地址,
最低有效位存于最低内存处。UDP/TCP/IP协议规定:把接收到的第一个字节当作高位字节看待,这 就要求发送端发送的第一个字节是高位字节;而在发送端发送数据时, 发送的第一个字节是该数值在内存中的起始地址处对应的那个字节, 也就是说,该数值在内存中的起始地址处对应的那个字节就是要发送 的第一个高位字节
所以:网络字节序就是大端字节序。
但是我们系统的本机字节序是小端字节序,因此需要对应的接口进 行转换addrlen: 地址的长度 实际上就是struct sockaddr_in这个类型的长度
返回值:成功返回0,失败返回-1,同时errno被设置
III 字节序转换
SYNOPSIS#include <arpa/inet.h>//将主机字节序转换为网络字节序uint32_t htonl(uint32_t hostlong);uint16_t htons(uint16_t hostshort); //将网络字节序转换为主机字节序uint32_t ntohl(uint32_t netlong);uint16_t ntohs(uint16_t netshort);
函数说明:
说明:h -----host;n----network ;s------short;l----long。
htons()--"Host to Network Short"
htonl()--"Host to Network Long"
ntohs()--"Network to Host Short"
ntohl()--"Network to Host Long"
现在我们需要将主机字节序转换为网络字节序,选用短整型就可以,所以我们选用htons
IV 地址转换
上面有讲到点分式,网络字节序,主机字节序。这些都是ip在不同应用中的格式。
以ip地址127.0.0.1
为例:
第一步 127 . 0 . 0 . 1 把IP地址每一部分转换为8位的二进制数。
第二步 01111111 00000000 00000000 00000001 = 2130706433 (主机字节序)
然后把上面的四部分二进制数从右往左按部分重新排列,那就变为:
第三步 00000001 00000000 00000000 01111111 = 16777343 (网络字节序)
以下就是一些地址转换函数:
SYNOPSIS#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int inet_aton(const char *cp, struct in_addr *inp);in_addr_t inet_addr(const char *cp);//如果是结构体里面用结构体 采用这个就可以了in_addr_t inet_network(const char *cp);char *inet_ntoa(struct in_addr in);//将得到的ip地址转换成点分式字符串struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host);in_addr_t inet_lnaof(struct in_addr in);
V 监听
NAME 名称listen - listen for connections on a socket 在一个套接字上倾听连接//创建一个监听队列,监听我们的连接SYNOPSIS 概述#include <sys/socket.h>int listen(int s, int backlog);
参数解释:
s:表示在哪个套接字上面进行监听
backlog:你需要创建多长的队列,在这里我们需求不大,队列5 -10就可以
返回值:成功返回0,失败返回-1,同时errno被设置
VI accept
NAME 名称accept - 在一个套接字上接收一个连接SYNOPSIS 概述#include <sys/types.h>#include <sys/socket.h>int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
参数解释:
s:套接字
addr:保存连接对方的ip地址,实际上就是客户端的
addrlen:地址的长度,一定要带长度进去
返回值:返回一个连接套接字,服务器的通信是基于这个连接套接字的
失败返回-1,同时errno被设置
VII connect
NAMEconnect - initiate a connection on a socket//连接服务器SYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd:套接字
addr:服务器的ip地址,你需要提前准备
addrlen:这个地址的长度
返回值:成功返回0,失败返回-1,同时errno被设置
VIII 从套接字接收信息
SYNOPSIS#include <sys/types.h>#include <sys/socket.h> ssize_t read(int fd, void *buf, size_t count);ssize_t recv(int sockfd, void *buf, size_t len, int flags);ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
TCP上面三个函数都可以用,但是UDP是无连接的,因此只能使用recvfrom
recvfrom参数解释:
前面三个参数请参数read的
flags:一个标志 填0即可
src_addr:保存对方的ip地址
addrlen:保存对方的ip地址长度
返回值:成功返回实际读到的字节数
失败返回-1,同时errno被设置
IX 从套接字发送消息
#include <sys/types.h>#include <sys/socket.h>ssize_t write(int fd, const void *buf, size_t count);int send(int s, const void *msg, size_t len, int flags);int sendto(int s, const void *msg, size_t len, int flags, const structsockaddr *to, socklen_t tolen);
TCP上面三个函数都可以用,UDP只能使用sendto
参数解释:flags:一个标志
to:对方的ip地址 你要把这个消息发送给谁
tolen:你的地址的长度
返回值:成功返回实际发送的字节数
失败返回-1,同时errno被设置
X 关闭套接字
SYNOPSIS#include <sys/socket.h>int close(int fd);//关闭套接字的读写int shutdown(int sockfd, int how);
参数解释:
sockfd:套接字
how:怎么关闭
SHUT_RD 关闭读
SHUT_WR 关闭写
SHUT_RDWR 关闭读写
5、网络配置
1、确保你的网卡里面有两个虚拟网卡,你的有线网卡的型号也在这里面看
在更改适配器里面看是否有VMnet1 VMnet8
2、配置电脑的有线网卡ip
进入更改适配器选项-> 右击你的有线网卡 -> 属性 -> TCP/IPV4 -> 使用下面ip地址 ->设置你的ip -> 确定
其中: 192.168.1.x -> 电脑
192.168.1.y -> 乌班图
192.168.1.z -> 开发板
x,y,z在10 ~ 250之间,不相同即可
子网掩码 255.255.255.0
网关:192.168.1.1
3、配置ubuntu的ip
首先关闭ubuntu
以管理员方式打开VMware,不要打开乌班图(选中这个乌班图即可)
palyer版本 -> player -> 虚拟机设置 -> 网络适配器 -> 选择桥接模式 -> 适配适配器
-> 一定要选择你的有线网卡 -> 前面的√只打这一个 -> 确定 -> 开启这个乌班图
pro版本 -> 编辑 -> 虚拟网络编辑器 -> 桥接至 你的有线网卡(不要选择自动) -> 确定
开启乌班图
右上键电源那个地方点击 -> 有线连接 -> 有线关闭 -> 右边的齿轮点进去-> IPV4 -> 手动 -> 按照windows填的方式填(但是ip不能和window一样) -> 应用 -> 打开有线连接
在终端我们可以看一下自己的ip是否改好,ifconfig命令
可以ping我们的windows的ip
ping 192.168.1.x -> 没有看到time是多少的就是没有通
4、配置开发板的ip
进入开发板的profile文件,写入 ifconfig eth0 192.168.1.z netmask 255.255.255.0 up(将192.168.1.z改成你自己设的具体的IP),这样开发板每次开机都会自己开网。
6、练习:实现简单的网络编程,客户端和服务器端可以实现通信
tcp_client.c
//客户端
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
//全局的套接字
int sockfd = -1;//将套接字创建好 并且绑定 监听
//将ip地址和端口号传进来 端口号释放需要时间(轮询机制)
void TcpInit(const char * ipaddr,unsigned short port)
{//1 创建套接字 ---- 什么2都是文件,因此你的网络通信也是一个文件sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){perror("server socket error");exit(1);//没有必要运行了}//2 我们需要将服务器的IP地址绑定到套接字struct sockaddr_in sa;sa.sin_family = AF_INET;//协议族sa.sin_port = htons(port);//端口号 内存是小端的 我们要转大端sa.sin_addr.s_addr = inet_addr(ipaddr);//将我们点分式的ip地址转换为一个大端整数//连接服务器int r = connect(sockfd,(struct sockaddr *)&sa,sizeof(sa));if(-1 == r){perror("connect error");exit(2);}}//开始正常的收发
void function(void)
{char buf[1024] = {0};while(1){printf("输入你要发送的信息(输入quit退出):");fflush(stdout);scanf("%s",buf);if(!strcmp(buf,"quit")){break;}send(sockfd,buf,strlen(buf) + 1,0);recv(sockfd,buf,1024,0);printf("服务器回我的信息是:%s\n",buf);}
}int main(int argc,char * argv[])
{if(argc < 3){printf("参数都不齐\n");return -1;}TcpInit(argv[1],atoi(argv[2]));function();close(sockfd);return 0;
}
tcp_sever.c
//服务器
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>//全局的套接字
int sockfd = -1;//将套接字创建好 并且绑定 监听
//将ip地址和端口号传进来 端口号释放需要时间(轮询机制)
void TcpInit(const char * ipaddr,unsigned short port)
{//1 创建套接字 ---- 神马都是文件,因此你的网络通信也是一个文件sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){perror("server socket error");exit(1);//没有必要运行了}//2 我们需要将服务器的IP地址绑定到套接字struct sockaddr_in sa;sa.sin_family = AF_INET;//协议族sa.sin_port = htons(port);//端口号 内存是小端的 我们要转大端sa.sin_addr.s_addr = inet_addr(ipaddr);//将我们点分式的ip地址转换为一个大端整数//printf("ipaddr = %x port = %x\n",inet_addr(ipaddr),htons(port));int r = bind(sockfd,(struct sockaddr *)&sa,sizeof(sa));if(-1 == r){perror("server bind error");exit(2);//没有必要运行了}//3 监听连接 ---- 创建一个监听队列 建立5个10个可以了listen(sockfd,5);}//专门用于去服务一个客户的线程
void * ClinetFunction(void * arg)
{pthread_detach(pthread_self());//将其分离int * accceptfd = (int *)arg;printf(" * accceptfd = %d\n", * accceptfd);char buf[1024] = {0};//你发什么信息过来 我就在这个信息之前加上一节 然后回发给你while(1){char sendbuf[1024] = {"SB250->"};int r = recv(*accceptfd,buf,1024,0);//阻塞等待数据过来if(-1 == r){perror("recv error");break;}else if(0 == r)//客户端已经断了{printf("对方断开连接了\n");break;}else//接收到信息了{printf("recv buf = %s\n",buf);strcat(sendbuf,buf);send(*accceptfd,sendbuf,strlen(sendbuf) + 1,0);}}close(*accceptfd);free(accceptfd);}//等待客户端的连接
void waitconnect(void)
{//我们要基于这个连接套接字去通信struct sockaddr_in sa;socklen_t addrlen = sizeof(sa);while(1){printf("一直等待对方的连接.......\n");int * accceptfd = malloc(4);//避免释放 因此我们要动态内存分配才可以*accceptfd = accept(sockfd,(struct sockaddr *)&sa,&addrlen);printf("连接者为:%s %d\n",inet_ntoa(sa.sin_addr),ntohs(sa.sin_port));//开一个线程出去 让它去服务与我的连接pthread_t thread;if(pthread_create(&thread,NULL,ClinetFunction,(void *)accceptfd) != 0){perror("create thread error");continue;}}close(sockfd);
}//通过main函数的参数 我们将这个ip地址和端口给进去
//./a.out 192.168.31.251 8888
int main(int argc,char * argv[])
{if(argc < 3){printf("参数都不齐\n");return -1;}TcpInit(argv[1],atoi(argv[2]));waitconnect();return 0;
}
参考博客:
计算机网络——网络字节序(大端字节序(Big Endian)\小端字节序(Little Endian))-CSDN博客
相关文章:
![](https://www.ngui.cc/images/no-images.jpg)
通信原理课设(gec6818) 006:网络编程
目录 1、概念 2、通信 3、通信基本流程 TCP: UDP: 4、函数 I 创建套接字 II 绑定地址 III 字节序转换 IV 地址转换 V 监听 VI accept VII connect VIII 从套接字接收信息 IX 从套接字发送消息 X 关闭套接字 5、网络配置 1、确保你的网卡里面有两个虚拟网卡&a…...
![](https://img-blog.csdnimg.cn/img_convert/a3cb7b3ae5b710c44e407c3b6e02b1e1.png)
一体化、一站式!智能视频客服加码全媒体云呼叫中心能力
凭借对电话、短信、邮件、社交媒体、视频等数种沟通渠道强大的统一集成能力,全媒体云呼叫中心已跃升成为现代企业客户服务的核心工具,高效便捷地为企业提供客户服务。而随着消费者需求愈加多元化和个性化,传统的语音通话方式已无法满足部分消…...
![](https://www.ngui.cc/images/no-images.jpg)
Vue的watch功能:实现响应式数据更新
watch是vue内部提供的一个用于侦听功能的更通用的方法,其用来响应数据的变化,通过特定的数据变化驱动一些操作。简言之:当需要被watch监听的数据发生变化时就会被执行watch中的逻辑。实现数据的实时更新! 普通监听 <template…...
![](https://www.ngui.cc/images/no-images.jpg)
兔单抗制备方法的发展-杂交瘤技术|卡梅德生物
兔单克隆抗体技术是近年来在抗体研究领域中取得的重要进展之一。研究人员通过改进抗原设计、免疫策略和单克隆B细胞培养条件,提高了单克隆抗体的产量和特异性。相比于传统的小鼠单克隆抗体技术,兔单克隆抗体技术具有更大的抗原特异性和更高的亲和力&…...
![](https://img-blog.csdnimg.cn/direct/fedb142c07554d6abe36b364b55f0d2f.png)
【数据结构】图论与并查集
一、并查集 1.原理 简单的讲并查集,就是查询两个个元素,是否在一个集合当中,这里的集合用树的形式进行表示。并查集的本质就是森林, 即多棵树。 我们再来简单的举个例子: 假设此时的你是大一新生,刚进入大学,肯定是…...
![](https://img-blog.csdnimg.cn/img_convert/0df54ced796c440ecbd64b71764e32b8.png)
冲刺港股IPO,速腾聚创「承压」
对于「光鲜」的激光雷达公司来说,当下最难的问题是:如何说服投资者相信,前装市场能够按照预期定点订单兑现。 今年,作为国内高阶智驾头部车企之一的华为,在陆续推出的新车型上开始「降本」。其中,问界智驾版…...
![](https://img-blog.csdnimg.cn/direct/10083832d11b45c08ffd0bae3b9d0ec5.png)
Linux基础知识点(五-信号)
一、信号的基本概念 1.1 信号的概念 信号(signal),又称为软中断信号,用于通知进程发生了异步事件,它是Linux系统响应某些条件而产生的一个事件,它是在软件层次上对中断机制的一种模拟,是一种异…...
![](https://img-blog.csdnimg.cn/img_convert/cb53b9bbb4c72ceb8c7cc0ff368deb60.gif)
SpringBoot 一个注解实现数据脱敏
什么是数据脱敏 数据脱敏是指对某些敏感信息,例如姓名、身份证号码、手机号、固定电话、银行卡号、邮箱等个人信息,通过脱敏算法进行数据变形,以保护敏感隐私数据。 数据脱敏通常涉及以下几种主要方法: 替换: 将原始…...
![](https://www.ngui.cc/images/no-images.jpg)
记录:开始学习网络安全
本文持续更新学习进度 背景 在私企干了5年虚拟化、云原生相关的运维,学到了很多,但不成体系。老板是清华毕业法国留学在德勤干过,最后回国创业的野路子。我工作是为了更好的生活,我挺担心老板因为家庭变故或者炒个原油宝&#x…...
![](https://www.ngui.cc/images/no-images.jpg)
C语言—第1次作业:编译与连接基础知识
常做练习巩固知识 本次作业答案链接如下: 答案解析——C语言—第1次作业:编译与连接基础知识 1.字符串的结束标志是:( ) A.是0 B.是EOF C. 是\0 D.是空格 2.关于C语言关键字说法正确的是:( ) A.关…...
![](https://www.ngui.cc/images/no-images.jpg)
not attached to window manager问题解决
关于出现这个问题,一般是因为Activity已经在finish了,但是还在dialog.show(),或者dialog.dismiss().导致window manager无法管理dialog。解决办法如下: /** * 20210913 安全关闭对话框 . * 避免报:not attac…...
![](https://img-blog.csdnimg.cn/direct/26388348d1624997b530ad40c60d6729.png)
影视后期: PR调色处理,调色工具面板介绍
写在前面 整理一些影视后期的相关笔记博文为 Pr 调色处理,涉及调色工具面板简单认知包括 lumetri 颜色和范围面板理解不足小伙伴帮忙指正 元旦快乐哦 _ 名词解释 饱和度 是指色彩的鲜艳程度,也被称为色彩的纯度。具体来说,它表示色相中灰色…...
![](https://www.ngui.cc/images/no-images.jpg)
ARM AArch64的虚拟化(virtualization)详解(上)
目录 一、概述 开始之前 二、虚拟化介绍 为什么虚拟化很重要...
![](https://img-blog.csdnimg.cn/2d6e22a375af4cac932d76a538560ade.png)
计算机组成原理知识总结
目录 第一章、计算机系统概述知识框架:1.冯诺依曼机和存储程序的概念?2.计算机的工作过程?3.在计算机系统结构中,什么是编译?什么是解释?4.描述一下指令执行过程?1) 取指令: PC 一&g…...
![](https://www.ngui.cc/images/no-images.jpg)
springboot学习(八十五) 解决springboot3.2找不到资源无法抛出404错误的问题
前言 springboot3.2以下可以定义ErrorPageRegistrar将404错误转发到一个接口地址,但升级到springboot3.2(spring6.1)后,该配置不生效,抛出了500错误。 以前的错误页面处理如下: ConditionalOnClass(ErrorPageRegist…...
![](https://img-blog.csdnimg.cn/direct/5288261094c04ff7afb4b1e96877b42b.png)
OpenHarmony 应用通用签名
一.背景 由于hap包需要经过签名才能安装到设备上,在DevEco Studio可以进行自动签名,但是自动签名只能安装在当前的设备上,在其他设备上不能安装,所以我们需要进行通用的手动签名,手动签名HarmonyOS和OpenHarmony流程是…...
![](https://img-blog.csdnimg.cn/direct/88d34f14400a470b8f8fc40523b0552f.png)
Redis:原理+项目实战——Redis实战1(session实现短信登录(并剖析问题))
👨🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理速成项目实战——Redis的Java客户端 📚订阅专栏:Redis速成 希望文章对你们有所帮助…...
![](https://img-blog.csdnimg.cn/direct/6f5c949391ab49939bcdd4f582429c2d.png)
交叉编译aarch64架构支持openssl的curl、libcurl
本文档旨在指导读者在x86_64平台上交叉编译curl和openssl库以支持aarch64架构。在开始之前,请确保您的系统环境已正确配置。 1. 系统环境准备 系统是基于Ubuntu 20.04 LTS,高版本可能会有问题。首页,安装必要的开发工具和库文件。打开终端并…...
![](https://img-blog.csdnimg.cn/img_convert/92083ff10799f103a9cf90c5acea50b7.png)
扩展名是.KEY的文件可能有不同的存在,打开方式也因此不同
本文解释了使用KEY文件扩展名的所有不同格式,以及如何在可能的情况下打开和转换每种格式。 KEY文件的定义 KEY文件扩展名可能是用于注册软件程序的纯文本或加密的通用许可证密钥文件。不同的应用程序使用不同的KEY文件来注册各自的软件,并证明用户是合…...
![](https://img-blog.csdnimg.cn/direct/760b17e3724c44cea72bb9a726148fd3.png)
软件工程总复习笔记
软件工程课程复习提纲 文章目录 软件工程课程复习提纲一、基本知识点1. 软件工程的概念及目标2. 软件危机的概念及典型表现3. 瀑布模型的概念及特点4. 快速原型模型的特点5. 螺旋模型的基本思想6. 软件生命周期的概念及划分为哪几个阶段7. 软件需求的定义8. 常见的软件需求获取…...
![](https://img-blog.csdnimg.cn/direct/9f9eb8a721c74a77b2e1eb6e07bc8aa9.png)
蓝桥杯-每日刷题-030
打印等边三角形 一、题目要求 题目描述 输出等边三角形:输入n值,输出高度为n的等边三角形。输入格式 输入存在多组测试数据。对于每组测试数据输入一个正整数n(1<n<100)。输出格式 对于每组测试数据输出对应的等边三角形。每组测试数据最后输出一…...
![](https://www.ngui.cc/images/no-images.jpg)
AI赋能游戏开发,如何更好地处理随之而来的海量数据,更好地利用开发游戏?
人工智能(AI)正在改变我们所知的游戏行业。它为3A工作室、独立开发者和业余爱好者提供了工具,让他们能够更轻松地创建以前需要大量时间和资源的项目。尤其是,虚幻引擎的AI工具已经取得了显著的进步。 虚幻引擎AI拥有专门用于游戏…...
![](https://www.ngui.cc/images/no-images.jpg)
Serverless架构学习路线及平台对比
在云计算领域,Serverless架构已经成为了一个重要的趋势。本文将为你提供一条清晰的Serverless架构学习路线,帮助你系统地掌握这个领域的知识,并对比国内外的Serverless平台的优缺点。 一、基础理论学习 首先,我们需要理解Server…...
![](https://www.ngui.cc/images/no-images.jpg)
解决ROS含动态参数的Config文件无法正确识别的错误
问题描述 功能包名为paddle_detection 在工作空间下, 通过catkin_make可以正常通过编译且执行无异常, 可以通过bloom-generate rosdebian生成依赖 但是在将其打包成deb包的过程中fakeroot debian/rules binary报错 fatal error: paddle_detection/paddle_detectionConfig.…...
![](https://www.ngui.cc/images/no-images.jpg)
探索 PyTorch 中的 torch.nn 模块**(1)
目录 引言 torch.nn使用和详解 Parameter 函数作用 使用技巧 使用方法和示例 UninitializedParameter 特点和用途 可进行的操作 使用示例 UninitializedBuffer 特点和用途 可进行的操作 使用示例 Module**(重点) 关键特性和功能 举例说…...
![](https://www.ngui.cc/images/no-images.jpg)
【WPF.NET开发】预览事件
本文内容 先决条件预览标记为“已处理”的事件通过控件解决事件禁止问题 预览事件,也称为隧道事件,是从应用程序根元素向下遍历元素树到引发事件的元素的路由事件。 引发事件的元素在事件数据中报告为Source 。 并非所有事件场景都支持或需要预览事件。…...
![](https://img-blog.csdnimg.cn/direct/abc4259ac9914f32b3b3a76a49b33c8b.png)
JDBC->SpringJDBC->Mybatis封装JDBC
一、JDBC介绍 Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们…...
![](https://www.ngui.cc/images/no-images.jpg)
ts中的keyof 关键字
const getVal <T,K extends keyof T>(obj:T,key:K) : T[K]>{return obj[key]; }使用了 keyof 关键字。keyof 是 TypeScript 的一个特性,它返回一个字符串字面量类型,表示对象类型的所有属性键的联合类型。 这段代码定义了一个泛型函数 gatVal&…...
![](https://img-blog.csdnimg.cn/direct/4f11e1a0627549d5bbd6775d27fd900c.png)
Head First Design Patterns - 装饰者模式
什么是装饰者模式 装饰者模式动态地将额外责任附加到对象上。对于拓展功能,装饰者提供子类化的弹性替代方案。 --《Head First Design Patterns》中的定义 为什么会有装饰者模式 根据上述定义,简单来说,装饰者模式就是对原有的类,…...
![](https://img-blog.csdnimg.cn/direct/5a10ecab4f7746f58cb3c440fb50ebff.png)
MySQL 执行过程
MySQL 的执行流程也确实是一个复杂的过程,它涉及多个组件的协同工作,故而在面试或者工作的过程中很容易陷入迷惑和误区。 MySQL 执行过程 本篇将以 MySQL 常见的 InnoDB 存储引擎为例,为大家详细介绍 SQL 语句的执行流程。从连接器开始&…...
![](/images/no-images.jpg)
dedecms双语网站/友情链接论坛
物联网事业部总裁DipeshPatel于台北国际计算机展的CPX论坛,发表“迈入物联网时代的机会与挑战”(Meetingthe Challengesof Scalingthe IoT)演说,畅谈物联网的最新技术与发展趋势,和ARM在物联网的发展近况。 ARM物联网事…...
![](/images/no-images.jpg)
平湖新埭哪里有做网站的/外链发布平台
电脑史话(40)——窗含千秋雪凡使用过IBM PC机的人都知道,在DOS操作系统的控制下,无论让电脑干什么,都必须记住各种操作命令,在键盘上不停敲打,输入一大串文字字符,带来诸多不便。 1985年11月,微…...
![](https://img-blog.csdnimg.cn/20200408210914620.png)
做网站客户尾款老不给怎么办/创建自己的网页
LeetCode-面试题13. 机器人的运动范围-中等 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行…...
![](/images/no-images.jpg)
玉环市建设工程检测中心网站/网络营销主要有哪些特点
单行注释: CTRL / 当行取消注释(一样的): CTRL / 多行注释: CTRL SHIFT / 多行取消注释(斜杠换成反斜杠): CTRL SHIFT \ 转载于:https://www.cnblogs.com/lijins/p/100994…...
![](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg#pic_center)
深圳市网站建设公司好不好/营销型网站分为哪几种
face recognition 项目实际使用 最近在一个公众号上看到一个推荐的github上的项目,号称是最简单,最容易上手的人脸识别项目,折腾了两天才算把这个模块装好,其实大部分时间都花在了安装各种依赖包上,cmake,…...
![](/images/no-images.jpg)
做年报的网站怎么登不上去了/如何创建个人网站免费
保存不存在的文件时的问题文件权限,最初创建为新文件.现在,一切顺利,保存的文件似乎具有模式644.为了使文件保存为模式777,我必须在此处更改什么?万分感谢任何提示,线索或答案.我认为与此相关的代码包括:/* write to file */self::writeFileContent($pat…...