网络编程:OSI协议,TCP/IP协议,IP地址,UDP编程
目录
国际网络通信协议标准:
1.OSI协议:
2.TCP/IP协议模型:
应用层 :
传输层:
网络层: IPV4协议 IP地址
IP地址的划分: 公有地址 私有地址
MAC地址:
端口号:
UDP编程
1.套接字:
2.流程
3.函数接口
(1) socket
(2)sendto
(3) inet_addr
(4) htons
(5) bind
(6)recvfrom
主机作为发送端
主机作为接收端
网络:
协议:通信双方约定的一套标准
国际网络通信协议标准:
1.OSI协议:
应用层 发送的数据内容
表示层 数据是否加密
会话层 是否建立会话连接
传输层 数据传输的方式
网络层 数据的路由
数据链路层 局域网内部通信
物理层 物理介质的连接
2.TCP/IP协议模型:
应用层 发送的数据内容
传输层 数据传输的方式
网络层 数据由一台主机到达另一台主机
网络接口层 物理介质连接
应用层 :
FTP 文件传输协议
TFTP 简单文件传输协议
HTTP 超文本传输协议
HTTPS 安全超文本传输协议
SMTP 简单邮件传输协议
TELNET 网络终端登录协议
DNS 域名系统
..
传输层:
TCP 传输控制协议
UDP 用户数据报协议
UDP:不安全、不可靠的传输方式
UDP机制简单
UDP占用的资源开销比较小
TCP:安全、可靠的传输方式
TCP机制复杂
TCP占用的资源开销比较大
三次握手建立连接,确认双方能够通信
通信过程中保障数据传输的完整性
四次挥手断开连接,确保数据传输的完整
网络层:
IPV4协议
IP地址
管理员IP地址形式:192.168.0.167
内存IP地址形式: 11000000.10101000.00000000.10100111
IP地址 = 网络位 + 主机位
网络位:IP地址所属的网段(局域网的编号)
主机位:局域网中的第几台主机
网段号:网络位不变,主机位全为0
广播号:网络位不变, 主机位全为1
子网掩码:每个IP地址都会搭配一个子网掩码,用来区分IP地址的网络位及主机位
子网掩码展开成二进制,1对应的部分就是IP地址的网络位,0对应的部分就是IP地址的主机位
192.168.0.167
255.255.255.0
11000000.10101000.00000000.10100111
11111111.11111111.11111111.00000000
网段号192.168.0.0
广播号192.168.0.255
IP地址的划分:
公有地址
私有地址
A类:1.0.0.0 ~ 126.255.255.255
子网掩码:255.0.0.0
管理超大规模型网络
私有地址:10.0.0.0 ~ 10.255.255.255
B类:128.0.0.0 ~ 191.255.255.255
子网掩码:255.255.0.0
管理大中规模型网络
私有地址:172.16.0.0 - 172.31.255.255
C类:192.0.0.0 ~ 223.255.255.255
子网掩码:255.255.255.0
管理中小规模型网络
私有地址:192.168.0.0 ~ 192.168.255.255
D类:224.0.0.0 ~ 239.255.255.255
用于组播:255.255.255.0
E类:240.0.0.0 ~ 255.255.255.255
用于实验和研究:255.255.255.0
MAC地址:
设备自带网卡的地址(该地址是唯一的)
端口号:
找到同一台主机不同的应用程序
UDP编程
1.套接字:
实现Linux系统下的网络通信
套接字:一次通信对象的抽象
2.流程
发送端流程:1.创建套接字
2.发送信息
3.关闭套接字
接收端流程: 1.创建套接字
2.绑定IP和Port
3.接收信息
4.关闭套接字
3.函数接口
(1) socket
socket
int socket(int domain, int type, int protocol);
功能:
创建套接字
参数:
domain: AF_INET 表示IPV4协议
type:套接字类型
SOCK_STREAM:流式套接字
SOCK_DGRAM:数据报套接字
SOCK_RAW:原始套接字
protocol:
TCP和UDP协议:0
返回值:
成功返回用来通信的文件描述符
失败返回-1
(2)sendto
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如果sendto对应的套接字没有绑定端口,则sendto绑定一个随机端口完成发送功能
(3) inet_addr
inet_addr
in_addr_t inet_addr(const char *cp);
功能:
将字符串的IP地址转换为32位的地址类型
(4) htons
htons
uint16_t htons(uint16_t hostshort);
功能:
将本地字节序(小端)转换成网络大端字节序
(5) bind
bind
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:
将套接字与IP地址和端口进行绑定
参数:
addr:绑定地址结构体空间首地址
addrlen:绑定地址空间大小
返回值:
成功返回0
失败返回-1
注意:
只能绑定自己的IP地址
(6)recvfrom
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
功能:
接收信息
参数:
sockfd:套接字文件描述符
buf:接收数据空间首地址
len:接收数据长度
flags:接收的属性 默认为0
src_addr:存放发送方地址空间的地址
addrlen: 要接收的发送方地址的长度
返回值:
成功返回实际接收字节数
失败返回-1
练习一:
主机作为发送端
#include "../head.h"
//主机作为发送方
int main()
{int sockfd=0;ssize_t nsize=0;struct sockaddr_in recvaddr;struct sockaddr_in sendaddr;//创建用来通信的套接字sockfd=socket(AF_INET,SOCK_DGRAM,0);//AF_INET:IPV4协议族,SOCK_DGRAM:UDP数据报套接字if(sockfd==-1){perror("failed to socket");return -1;}//将发送端套接字与IP地址和端口号绑定sendaddr.sin_family=AF_INET;sendaddr.sin_port=htons(30000);sendaddr.sin_addr.s_addr=inet_addr("192.168.0.185");bind(sockfd,(struct sockaddr *)&sendaddr,sizeof(sendaddr));//为目的地址赋值recvaddr.sin_family=AF_INET;//协议族为IPV4recvaddr.sin_port=htons(8080);//端口号( htons() 将本地字节序(小端)转换为网络字节序(大端))(发送给wltszs4.3.29网络调试助手)recvaddr.sin_addr.s_addr=inet_addr("192.168.0.135");//IP地址( inet_addr() 将字符串类型转换为二进制地址类型)//向目的地址发送数据nsize=sendto(sockfd,"66666666666",12,0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));//注意强制类型转换if(nsize==-1){perror("failed to sendto");return 0;}printf("发送成功\n");//关闭套接字close(sockfd);return 0;
}
主机作为接收端
#include "../head.h"
int main()
{int sockfd=0;int ret=0;char tmpbuff[200]={0};ssize_t nsize=0;struct sockaddr_in recvaddr;//创建套接字sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd==-1){perror("failed to socket");return -1;}//将套接字和IP地址与端口号绑定recvaddr.sin_family=AF_INET;recvaddr.sin_port=htons(20000);recvaddr.sin_addr.s_addr=inet_addr("192.168.0.185");ret=bind(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));if(ret==-1){perror("failed to bind");return 0;}//接受数据nsize=recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,NULL,NULL);if(nsize==-1){perror("failed to recvfrom");return 0;}//打印数据printf("接收到字节数:%ld,内容为:%s\n",nsize,tmpbuff);//关闭套接字close(sockfd);return 0;
}
练习二:利用UDP编程发送文件
发送端send.c
#include "../head.h"
int main()
{int sockfd;int ret=0;FILE *fp=NULL;struct sockaddr_in recvaddr;char readbuff[1024]={0};size_t size=0;ssize_t nsize=0;//创建套接字sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd==-1){perror("failed to socket");return -1;}//为目的地址赋值recvaddr.sin_family=AF_INET;recvaddr.sin_port=htons(30000);recvaddr.sin_addr.s_addr=inet_addr("192.168.0.187");//输入要发送的文件名printf("请输入要发送的文件名:");fgets(readbuff,sizeof(readbuff),stdin);readbuff[strlen(readbuff)-1]='\0';//打开该文件fp=fopen(readbuff,"r");if(fp==NULL){perror("failed to fopen send.txt");return -1;}//发送文件名nsize=sendto(sockfd,readbuff,strlen(readbuff)+1,0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));if(nsize==-1){perror("failed to sendto");return -1;}
//发送文件内容
while(1)
{size=fread(readbuff,1,sizeof(readbuff),fp);if(size<=0){break;}nsize=sendto(sockfd,readbuff,size,0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));if(nsize==-1){perror("failed to sendto");return -1;}
}
//发送文件结尾关闭标志sprintf(readbuff,".quit");nsize=sendto(sockfd,readbuff,size,0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));if(nsize==-1){perror("failed to sendto");return -1;}//关闭套接字和文件close(sockfd);fclose(fp);return 0; }
接收文件端
#include "../head.h"
int main()
{int sockfd;int ret=0;FILE *fp=NULL;char filename[100]={0};char tmpbuff[1024]={0};struct sockaddr_in recvaddr;char readbuff[1024]={0};size_t size=0;ssize_t nsize=0;//创建套接字sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd==-1){perror("failed to socket");return -1;}//绑定接收IP地址和套接字,端口号recvaddr.sin_family=AF_INET;recvaddr.sin_port=htons(30000);recvaddr.sin_addr.s_addr=inet_addr("192.168.0.187");bind(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));//接收文件名nsize=recvfrom(sockfd,filename,sizeof(filename),0,NULL,NULL);if(nsize==-1){perror("failed to recvfrom");return -1;}//创建文件fp=fopen(filename,"w");if(fp==NULL){perror("failed to fopen");return -1;}//接收文件内容while (1){nsize=recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,NULL,NULL);if(nsize==0){break;}if(!strcmp(tmpbuff,".quit")){break;}fwrite(tmpbuff,nsize,1,fp);}//关闭套接字和文件close(sockfd);fclose(fp);return 0; }
练习三:利用UDP编程实现聊天功能
1.(进程实现)
send.c
#include "../head.h"
int main()
{pid_t pid;struct sockaddr_in sendaddr;struct sockaddr_in recvaddr;char tmpbuff[100]={0};ssize_t size_send;ssize_t size_recv;int sockfd=0;sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd==-1){perror("failed to socket");return -1;}recvaddr.sin_family=AF_INET;recvaddr.sin_port=htons(30000);recvaddr.sin_addr.s_addr=inet_addr("192.168.0.187");//第一次发送是为了建立连接,数据可随机发送,不打印size_send = sendto(sockfd,"hello",6,0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));if(size_send==-1){perror("failed to sendto");return -1;}pid=fork();if(pid==-1){perror("failed to fork");return -1;}if(pid==0){ while (1){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);tmpbuff[strlen(tmpbuff)-1]='\0';size_send=sendto(sockfd,tmpbuff,strlen(tmpbuff),0,(struct sockaddr *)&recvaddr,sizeof(recvaddr));if(size_send==-1){perror("failed to sendto");return -1;}if(!strcmp(tmpbuff,".quit")){break;}}kill(getppid(),SIGKILL);}else if(pid>0){while(1){memset(tmpbuff,0,sizeof(tmpbuff));size_recv = recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,NULL,NULL);if(size_recv==-1){perror("failed to recvfrom");return -1;}if(!strcmp(tmpbuff,".quit")){break;}printf("RECV:%s\n",tmpbuff);}kill(pid,SIGKILL);}close(sockfd);return 0;}
recv.c
#include "../head.h"
int main()
{pid_t pid;struct sockaddr_in sendaddr;struct sockaddr_in recvaddr;size_t size_send;size_t size_recv;char tmpbuff[100]={0};socklen_t addrlen=sizeof(sendaddr);int ret=0;int sockfd=0;sockfd=socket(AF_INET,SOCK_DGRAM,0);if(sockfd==-1){perror("failed to socket");return -1;}recvaddr.sin_family=AF_INET;recvaddr.sin_port=htons(30000);recvaddr.sin_addr.s_addr=inet_addr("192.168.0.187");ret=bind(sockfd,(struct sockaddr *)&recvaddr,sizeof(recvaddr));if(ret==-1){perror("failed to bind");return -1;}
//第一次接收是为了建立连接,数据不打印size_recv = recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,(struct sockaddr *)&sendaddr,&addrlen);if(size_recv==-1){perror("failed to recvfrom");return -1;}pid=fork();if(pid==-1){perror("failed to fork");return -1;}if(pid==0){while(1){memset(tmpbuff,0,sizeof(tmpbuff));size_recv = recvfrom(sockfd,tmpbuff,sizeof(tmpbuff),0,NULL,NULL);if(size_recv==-1){perror("failed to sendto");return -1;}if(!strcmp(tmpbuff,".quit")){break;}printf("RECV:%s\n",tmpbuff);}kill(getppid(),SIGKILL);}else if(pid>0){while (1){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);tmpbuff[strlen(tmpbuff)-1]='\0';size_send=sendto(sockfd,tmpbuff,strlen(tmpbuff),0,(struct sockaddr *)&sendaddr,sizeof(sendaddr));if(size_send==-1){perror("failed to sendto");return -1;}if(!strcmp(tmpbuff,".quit")){break;}}kill(pid,SIGKILL);}close(sockfd);return 0;}
2.(线程实现)
send.c
#include "../head.h"int sockfd = 0;
pthread_t tid1;
pthread_t tid2;
struct sockaddr_in recvaddr;void *thread1(void *arg)
{char tmpbuff[1024] = {0};ssize_t nsize = 0;while (1){memset(tmpbuff, 0, sizeof(tmpbuff));fgets(tmpbuff, sizeof(tmpbuff), stdin);tmpbuff[strlen(tmpbuff)-1] = '\0';nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (-1 == nsize){perror("fail to sendto");return NULL;}if (!strcmp(tmpbuff, ".quit")){break;}}pthread_cancel(tid2);return NULL;
}void *thread2(void *arg)
{ char tmpbuff[1024] = {0};ssize_t nsize = 0;while (1){memset(tmpbuff, 0, sizeof(tmpbuff));nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, NULL, NULL);if (-1 == nsize){perror("fail to recvfrom");return NULL;}if (!strcmp(tmpbuff, ".quit")){break;}printf("RECV:%s\n", tmpbuff);}pthread_cancel(tid1);return NULL;
}int main(void)
{//1.创建套接字char tmpbuff[1024] = {"hello"};ssize_t nsize = 0;recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(RECV_PORT);recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("fail to socket");return -1;}//2.发送一次nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (-1 == nsize){perror("fail to sendto");return -1;}//3.创建两个线程pthread_create(&tid1, NULL, thread1, NULL);pthread_create(&tid2, NULL, thread2, NULL);pthread_join(tid1, NULL);pthread_join(tid2, NULL);close(sockfd);return 0;
}
recv.c
#include "../head.h"int sockfd = 0;
pthread_t tid1;
pthread_t tid2;
struct sockaddr_in recvaddr;
struct sockaddr_in sendaddr;void *thread1(void *arg)
{char tmpbuff[1024] = {0};ssize_t nsize = 0;while (1){memset(tmpbuff, 0, sizeof(tmpbuff));fgets(tmpbuff, sizeof(tmpbuff), stdin);tmpbuff[strlen(tmpbuff)-1] = '\0';nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr));if (-1 == nsize){perror("fail to sendto");return NULL;}if (!strcmp(tmpbuff, ".quit")){break;}}pthread_cancel(tid2);return NULL;
}void *thread2(void *arg)
{ char tmpbuff[1024] = {0};ssize_t nsize = 0;while (1){memset(tmpbuff, 0, sizeof(tmpbuff));nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, NULL, NULL);if (-1 == nsize){perror("fail to recvfrom");return NULL;}if (!strcmp(tmpbuff, ".quit")){break;}printf("RECV:%s\n", tmpbuff);}pthread_cancel(tid1);return NULL;
}int main(void)
{//1.创建套接字char tmpbuff[1024] = {"hello"};ssize_t nsize = 0;int ret = 0;socklen_t addrlen = sizeof(sendaddr);recvaddr.sin_family = AF_INET;recvaddr.sin_port = htons(RECV_PORT);recvaddr.sin_addr.s_addr = inet_addr(RECV_IP);sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("fail to socket");return -1;}ret = bind(sockfd, (struct sockaddr *)&recvaddr, sizeof(recvaddr));if (-1 == ret){perror("fail to bind");return -1;}//2.接收一次nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, (struct sockaddr *)&sendaddr, &addrlen);if (-1 == nsize){perror("fail to recvfrom");return -1;}//3.创建两个线程pthread_create(&tid1, NULL, thread1, NULL);pthread_create(&tid2, NULL, thread2, NULL);pthread_join(tid1, NULL);pthread_join(tid2, NULL);close(sockfd);return 0;
}
相关文章:

网络编程:OSI协议,TCP/IP协议,IP地址,UDP编程
目录 国际网络通信协议标准: 1.OSI协议: 2.TCP/IP协议模型: 应用层 : 传输层: 网络层: IPV4协议 IP地址 IP地址的划分: 公有地址 私有地址 MA…...

QtExa001自动包装流水线的框架设计vs2019QT
QtExa001自动包装流水线的框架设计 工程代码: https://download.csdn.net/download/txwtech/89636815https://download.csdn.net/download/txwtech/89636815 主界面: 设置:进行参数配置,保存ini文件 调试:tcp/ip&…...
SpringBoot拦截器的使用介绍
SpringBoot拦截器的使用介绍 本篇文章主要讲的是 SpringBoot 拦截器的使用介绍。 1、定义拦截器 拦截器:所谓拦截器,就是能够在进行某个操作之前拦截请求,如果请求符合条件就允许在往下执行。 定义拦截器的几种方式。 1.1 实现HandleInt…...
Spring Boot应用中的资源分离与高效打包实践
在电商网站项目中,前端资源通常包括HTML、CSS、JavaScript、图片、字体等静态文件,以及Thymeleaf或Freemarker等模板引擎渲染的页面。将这些资源从Spring Boot主应用中分离出来,不仅有利于前后端团队的并行开发,还能提高应用的加载…...
分析 avformat_open_input 数据读取过程
------------------------------------------------------------ author: hjjdebug date: 2024年 08月 13日 星期二 17:31:43 CST descriptor: 分析 avformat_open_input 数据读取过程 ------------------------------------------------------------ avformat_open_input 中读…...
Apache HOP (Hop Orchestration Platform) VS Data Integration (通常被称为 Kettle)
Apache HOP (Hop Orchestration Platform) 和 Data Integration (通常被称为 Kettle) 都是强大的 ETL (Extract, Transform, Load) 工具, 它们都由 Hitachi Vantara 开发和支持。尽管它们有着相似的目标,即帮助用户进行数据集成任务,但它们在…...

如何判断一个dll/exe是32位还是64位
通过记事本判断(可判断C或者C#) 64位、将dll用记事本打开,可以看到一堆乱码,但是找到乱码行的第一个PE,如果后面是d?则为64位 32位、将dll用记事本打开,可以看到一堆乱码,但是找到乱码行的第…...
加速网页加载,提升用户体验:HTML、JS 和 Vue 项目优化全攻略
在信息爆炸的时代,网页加载速度成为了用户体验的重中之重。试想一下,如果一个页面加载超过 3 秒,你还有耐心等待吗? 为了留住用户,提升转化率,网页优化势在必行! 本文将从 HTML、JavaScript 和…...

LVS服务器基础环境配置
环境配置 1 基础服务关闭 setenforce 0 # 临时关闭selinuxvi /etc/sysconfig/selinux # 永久关闭selinuxsystemctl disable --now firewalld # 关闭防火墙systemctl disable --now NetworkManager # 关闭网络管理器2 centos7软件仓库的配置 mount /dev/cdrom /media以防万一&…...
【Python OpenCV】使用OpenCV实现两张图片拼接
问题引入: 如何使用Python OpenCV实现两张图片的水平拼接和垂直拼接 代码实现: import cv2 import numpy as npdef image_hstack(image_path_1, image_path_2):"""两张图片左右拼接"""img1 cv2.imread(image_path_1)img…...
springboot jar -jar centos后台运行的几种方式
在CentOS系统中,如果你想要在后台运行一个Spring Boot应用程序,你可以使用nohup命令或者使用screen会话。以下是两种常用的方法: 1. **使用nohup命令**: nohup命令可以使进程在你退出SSH会话后继续运行。它还会把标准输出和标…...

【GitLab】使用 Docker 安装 GitLab:配置 SSH 端口
使用 Docker 安装 GitLab 要求修改ssh端口 GitLab 使用 SSH 通过 SSH 与 Git 交互。默认情况下,GitLab 使用端口22。 要在使用 GitLab Docker 映像时使用其他端口,您可以执行以下操作之一: 更改服务器的 SSH 端口(推荐)。 更改 GitLab Shell SSH 端口。 更改服务器的 SSH …...
【pdf文件生成】如何将盖章的文件生成PDF文件
一、提出问题 在我们的工作中,有时候上级让下级将盖章的文件生成PDF文件通过内部平台发送到上级邮箱,那如何解决呢?是去找一个扫描仪,还是用手机拍图转。用Python基实就能实现。 二、分析问题 现在网上好多的软件都是收费的&am…...

铝壳电阻在电路中的作用和影响是什么?
铝壳电阻,顾名思义,就是用铝材料制成的电阻。在电路中,它主要起到限流、分压、负载等作用。下面详细介绍铝壳电阻在电路中的作用和影响。 1. 限流作用:铝壳电阻可以限制电流的大小,防止电流过大而损坏电路。当电路中的…...
# Python 判断入参日期是周几
在数据分析和软件开发中,经常需要判断某个特定日期是星期几。Python 提供了强大的日期时间处理功能,可以轻松实现这一功能。本篇文章将介绍如何使用 Python 的内置库来判断给定日期是星期几,并提供具体实例。 1. 使用 datetime 模块 Python…...

井字棋游戏(HTML+CSS+JavaScript)
🌏个人博客主页:心.c 前言:这两天在写植物大战僵尸,写不动了,现在和大家分享一下之前我写的一个很简单的小游戏井字棋,这个没有AI,可以两个人一起玩,如果大家觉得我哪里写的有一些问…...

HTML 列表和容器元素——WEB开发系列10
HTML 提供了多种方式来组织和展示内容,其中包括无序列表、有序列表、分区元素 <div> 和内联元素 <span>、以及如何使用 <div> 进行布局和表格布局。 一、HTML 列表 1. 无序列表 (<ul>) 无序列表用于展…...
Java数组的高级使用技巧与性能优化
Java数组的高级使用技巧与性能优化 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! Java数组是程序设计中的基础数据结构,提供了一种存储固定大小的同类型元素的方式。本文将介绍Jav…...
python spyne报No module named ‘http.cookies‘的解决
python spyne报No module named ‘http.cookies’ python实现webservice服务端时,会使用spyne这个库,安装后,运行会提示No module named ‘http.cookies’。 尝试过不行的方法 pip install http.cookiespip install http.cookiejar 可行的…...

vmware虚拟机玩GPU显卡直通
安装好exsi以后,找到管理----硬件-----PCI设备,勾选想要直通的显卡,然后点击“切换直通” 切换以后可以看到列表中的直通列显示为活动就对了。 然后编辑虚拟机设置,CPU关闭硬件虚拟化(向客户机操作系统公开硬件辅助的…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...