第三天:实现网络编程基于tcp/udp协议在Ubuntu与gec6818开发板之间双向通信
互联网地址
每一台设备接入互联网后,都会举报一个唯一的地址编号
IP地址 INTERNET地址
internet地址 :它是协议上的一个逻辑地址
目前来说,我们主要的IP地址有两类 IPV4 IPV6
IPV4 其实就是使用一个32bit整数作为IP
IPV6 其实就是使用一个128bit整数作为IP
ipv4
1010 1100 0000 0010 0000 0001 0000 0001 人类是看不到的
172.2.1.1 给人看的"点分式"
每8bit组成一个十进制数,以 ‘.’ 隔开
2^32 个地址
这么多地址,怎么去管理?
类似电话号码 =区号+主机号
+86 0731 12345678
+86 中国大陆
0731 长沙
12345678 具体那个电话的号码
同理,ip地址也分为两个部分
ip地址=网络号+主机号
网络号:用于标识网络中的某个子网,占ip地址中的高x位
主机号:用于标识同一个子网内的不同主机,占地址中低的(32-x)位
也叫做 子网号 子网主机号
所占的bit位x又怎么确定呢?
netmask 子网掩码,用来确定一个ip地址中,网络号与主机号的占比
IP地址的bit位在子网掩码中对应的bit为1,就是网络号
在子网掩码中为0,就是主机号
比如:
ip 172.2.1.1
netmask 255.255.255.0
网络号 ip&netmask 172.2.1.0
主机号的范围 172.2.1.0 ~ 172.2.1.255
目前ip地址主要分为5类
我们常用的是C类网络
端口号
在网络中,可以提供ip地址来区分不同的网络设备
如果两个设备的IP相同 —》ip冲突,只有一台能够接入网络
问题;一台设备上,或许会运行多个网络应用
比如:我打开QQ给你们传文件,同时还在直播上课
那么网络中,怎么知道传递的数据,是由哪个网络应用发起的呢?
ip只能区分是那一台主机,不能区分是那一个应用
为了区分哪个网络应用传输的数据,需要用到端口号
TCP和UDP都是采用16bit无符号整数来作为端口号标识网络应用
IP —>标识网络中的某个设备
端口 —》标识设备上的某个网络应用
一台主机上的网络应用由:
ip地址+传输层协议(TCP/UDP)+端口号来确定
端口号 由 IANS 来管理
1-1023 众所周知的端口
比如 HTTP应用 80
FTP服务 20
…
1024-49151 注册端口,提供注册端口
49151-65536 动态或者私有端口,可以随便用
字节序
大端模式
高地址存储低字节 低地址存储高字节
小端模式
低地址存储低字节 高地址存储高字节
比如: int a = 0x12345678
&a = 0x4000
内存地址 | 大端模式存储内容 | 小端模式存储内容 |
---|---|---|
0x4000 | 0x12 | 0x78 |
0x4001 | 0x34 | 0x56 |
0x4002 | 0x56 | 0x34 |
0x4003 | 0x78 | 0x12 |
不同的系统对于内存的管理方法不同,可能采用大端模式,可能采用小端模式
练习:尝试写一个程序,判断自己的Linux系统是大端模式还是小端模式,并且输出结果
int a = 1; //0x00 00 00 01
char *p = &a
if(*p == 1)
{printf("小端模式\n");
}
else
{printf("大端模式\n");
}
网络字节序采用的是大端模式
网络接口 socket
网络通信接口 socket是一个简单易上手,功能强大的接口
有以下特点:
1.socket是一个编程接口(网络编程接口)
所有的网络程序,都需要基于socket
2.socket也是一个特殊的文件描述符
特殊:可以利用系统文件接口
比如 read write close
但是不能用lseek
它的内容不在文件系统中,也不在内核中,而是在"网络"中
3.socket 是TCP/IP协议的一种代码实现
但是它不仅限于TCP/IP协议,它还支持蓝牙协议,wifi协议,unix域协议
socket独立于具体协议的网络程序接口,位于应用层与传输层之间,负责衔接应用层与传输层
网络通信
网络通信的实现—》 API(应用程序编程接口)
1.socket 创建一个套接字
2.bind 不动,将一个地址(网络应用地址:IP+传输协议+端口)与套接字绑定
3.listen 监听,用于设定服务器监听套接字(监听后就可以获得客户端的请求)
4.accpet 等待连接请求的到来
5.connect 用于发起连接请求
6.通信 数据收发
read/write
recv/send
recefrom/send_to
7.关闭套接字
close 套接字也就是一个文件描述符罢了
思考 在网络通信在,服务器和客户端 双方的通信流程图
1 socket
NAMEsocket - create an endpoint for communicationSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>socket用来创建一个通信接口int socket(int domain, int type, int protocol);@domain:指定域,协议族AF_UNIX, AF_LOCAL Local communication unix(7)unix域协议/本地协议栈AF_INET IPv4 Internet protocols ip(7)IPV4协议族AF_INET6 IPv6 Internet protocols ipv6(7)IPV6协议族@type:指定套接字类型(选择传输层协议)SOCK_STREAM 流式套接字,面向TCP传输层协议SOCK_DGRAM 数据报套接字,面向UDP传输层协议SOCK_RAW 原始套接字@protocol:协议,指定具体那个协议一般为0,表示默认返回值:成功返回一个整数,是一个套接字文件描述符失败返回-1,并且errno被设置
2 bind
用于绑定服务器地址(IP+传输层协议+端口号)
NAMEbind - bind a name to a socketSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>bind 绑定一个"名字”给socket(套接字描述符)int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);@sockfd:指定套接字描述符,就是socket的返回值@addr:指向struct sockaddr 结构体指针,保存的是要绑定的地址@addrlen:地址长度,即参数addr的长度,sizeof (struct sockaddr)返回值:成功返回0,失败返回-1,并且errno被设置
关于网络应用的地址 =IP+传输层协议+端口号
在 头文件<sys/socket.h>中,定义了一个通用的网络应用地址结构体
struct sockaddr {sa_family_t sa_family;//指定协议栈,和socket函数的参数domain相同char sa_data[14];//数组保存网络应用地址(IP+传输层协议+端口号)}
上面这个结构体,并不是很好赋值和使用,一般在网络编程中,网络应用地址赋值可以采用定义在
/usr/include/netinet/in.h中的结构体 struct sockaddr_in
Structure describing an Internet socket address
以太网地址结构体
struct sockaddr_in{__SOCKADDR_COMMON (sin_);//协议栈 sin_familyin_port_t sin_port; /* 端口号,网络上一般是大端模式,计算机一般是小端模式 */struct in_addr sin_addr; /* 指定ip地址. typedef uint32_t in_addr_t;struct in_addr{in_addr_t s_addr;};*//* Pad to size of `struct sockaddr'. */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};
eg:某个网络应用
ip 172.2.1.11
端口 6666
struct sockaddr_in addr;//定义一个网络应用地址结构体addr
addr.sin_family=AF_INET;//协议族
addr.sin_port = htons(6666);//端口号是网络字节序,短整型
addr.sin_addr.s_addr = inet_addr(172.2.1.11);//点分式IP转为32bit整数
int ret = 0;//返回值
ret = bind(sockfd,(struct sockaddr)&addr,sizeof(addr));
if(ret == -1)
{perror("bind error");return -1;
}
//bind 之后,进程就有了一个网络应用地址,能够进行网络通信
端口本地字节序转网络字节序
h host 主机
to 转换成
n network 网络
s short 16bit
l long 32bit
NAMEhtonl, htons, ntohl, ntohs - convert values between host and network byte orderSYNOPSIS#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);将网络字节序转换成本地短整型参数就是需要转换的数据返回值就是转换之后的数据
点分式ip与32bit ip的转换
NAMEinet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation routinesSYNOPSIS#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>inet_addr是用来将cp指定的点分式ip转换成32bit整数ip返回in_addr_t inet_addr(const char *cp);@cp 指针,指向要转换的点分式字符串ip成功返回转换后的32bit整数
网络通信
网络通信的实现—》 API(应用程序编程接口)
1.socket 创建一个套接字
2.bind 不动,将一个地址(网络应用地址:IP+传输协议+端口)与套接字绑定
3.listen 监听,用于设定服务器监听套接字(监听后就可以获得客户端的请求)
4.accpet 等待连接请求的到来
5.connect 用于发起连接请求
6.通信 数据收发
read/write
recv/send
recefrom/send_to
7.关闭套接字
close 套接字也就是一个文件描述符罢了
思考 在网络通信在,服务器和客户端 双方的通信流程图
1 socket
NAMEsocket - create an endpoint for communicationSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>socket用来创建一个通信接口int socket(int domain, int type, int protocol);@domain:指定域,协议族AF_UNIX, AF_LOCAL Local communication unix(7)unix域协议/本地协议栈AF_INET IPv4 Internet protocols ip(7)IPV4协议族AF_INET6 IPv6 Internet protocols ipv6(7)IPV6协议族@type:指定套接字类型(选择传输层协议)SOCK_STREAM 流式套接字,面向TCP传输层协议SOCK_DGRAM 数据报套接字,面向UDP传输层协议SOCK_RAW 原始套接字@protocol:协议,指定具体那个协议一般为0,表示默认返回值:成功返回一个整数,是一个套接字文件描述符失败返回-1,并且errno被设置
2 bind
用于绑定服务器地址(IP+传输层协议+端口号)
NAMEbind - bind a name to a socketSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>bind 绑定一个"名字”给socket(套接字描述符)int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);@sockfd:指定套接字描述符,就是socket的返回值@addr:指向struct sockaddr 结构体指针,保存的是要绑定的地址@addrlen:地址长度,即参数addr的长度,sizeof (struct sockaddr)返回值:成功返回0,失败返回-1,并且errno被设置
关于网络应用的地址 =IP+传输层协议+端口号
在 头文件<sys/socket.h>中,定义了一个通用的网络应用地址结构体
struct sockaddr {sa_family_t sa_family;//指定协议栈,和socket函数的参数domain相同char sa_data[14];//数组保存网络应用地址(IP+传输层协议+端口号)}
上面这个结构体,并不是很好赋值和使用,一般在网络编程中,网络应用地址赋值可以采用定义在
/usr/include/netinet/in.h中的结构体 struct sockaddr_in
Structure describing an Internet socket address
以太网地址结构体
struct sockaddr_in{__SOCKADDR_COMMON (sin_);//协议栈 sin_familyin_port_t sin_port; /* 端口号,网络上一般是大端模式,计算机一般是小端模式 */struct in_addr sin_addr; /* 指定ip地址. typedef uint32_t in_addr_t;struct in_addr{in_addr_t s_addr;};*//* Pad to size of `struct sockaddr'. */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};
eg:某个网络应用
ip 172.2.1.11
端口 6666
struct sockaddr_in addr;//定义一个网络应用地址结构体addr
addr.sin_family=AF_INET;//协议族
addr.sin_port = htons(6666);//端口号是网络字节序,短整型
addr.sin_addr.s_addr = inet_addr(172.2.1.11);//点分式IP转为32bit整数
int ret = 0;//返回值
ret = bind(sockfd,(struct sockaddr)&addr,sizeof(addr));
if(ret == -1)
{perror("bind error");return -1;
}
//bind 之后,进程就有了一个网络应用地址,能够进行网络通信
端口本地字节序转网络字节序
h host 主机
to 转换成
n network 网络
s short 16bit
l long 32bit
NAMEhtonl, htons, ntohl, ntohs - convert values between host and network byte orderSYNOPSIS#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);将网络字节序转换成本地短整型参数就是需要转换的数据返回值就是转换之后的数据
点分式ip与32bit ip的转换
NAMEinet_aton, inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation routinesSYNOPSIS#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>inet_addr是用来将cp指定的点分式ip转换成32bit整数ip返回in_addr_t inet_addr(const char *cp);@cp 指针,指向要转换的点分式字符串ip成功返回转换后的32bit整数
3 listen
设置监听,用于监听网络上是否有客户端向“我”(服务器)发起链接请求
NAMElisten - listen for connections on a socketSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int listen(int sockfd, int backlog);@sockfd:指定要监听的套接字描述符@backlog:监听数量,大于0就行了返回值:成功返回0 失败返回-1,并且errno被设置
listen设置去监听套接字描述符,以便知道是否有人(客户端)向我(服务器)发起链接请求
但是listen只监听,不处理链接
Eg:
int ret = 0;
ret = listen(sockfd,10);
if (ret == -1)
{perror("listen error");
}
4 accept
用于等待链接请求,并且处理链接请求
accpet会阻塞进程的运行,直到客户端向服务器发起了链接请求(客户端调用了connect)
NAMEaccept, accept4 - accept a connection on a socketSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);@sockfd:指定套接字描述符@addr:指向struct sockaddr 结构体空间地址用于存储客户端的地址@addrlen:指socklen_t空间地址addrlen参数在使用前,需要先赋值 参数addr的长度因为在函数内部,会先利用addrlen的值来确保捕获导致内存溢出返回值:成功返回一个非负数,该值是一个文件描述符===》链接套接字描述符用于 服务器与链接的客户端的通信接口也就是说服务器是提供accept的返回值 来收发客户端的消息失败 返回-1,并且errno被设置
eg:
struct sockaddr_in caddr;//用于保存客户端的地址
socklen_t caddr_len = sizeof(caddr);//保存客户端地址长度,使用前保存该地址空间的长度
int connfd = 0;//用于保存 链接套接字描述符
connfd = accept(sockfd,(struct sockaddr*)&caddr,$caddr_len);
if(connfd == -1)
{perror("accept error");return -1;
}
如果accept指向成功,则connfd就是服务器与客户端之间的通信接口
如果我们是多次调用accept,那么九年允许多个客户端连接,并且每个客户端连接上来后
服务器上都有一一对应的connfd
5 connect
用于客户端向服务器发起链接请求
NAMEconnect - initiate a connection on a socketSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);@sockfd:指定套接字描述符@addr:指定要连接的服务器的地址@addrlen:addr的长度返回值:成功返回0失败返回-1,并且errno被设置
客户端调用 connect发起连接请求后,服务器的acceot接收到连接请求,并返回一个connfd用于服务器与客户端的通信接口
此时,客户端写入/发送数据给sockfd的数据就会通过网络传递给服务器的connfd
服务器就可以从connfd中读取/接收 这些数据
eg:
int ret = 0;
struct sockaddr_in saddr;
saddr.sin_family=AF_INET;//IPV4协议族
saddr.sin_port = htons(6666);//端口号是网络字节序,短整型
saddr.sin_addr.s_addr = inet_addr(172.2.1.110);//客户端的ip
ret = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if (ret == -1)
{perror("connect error");return -1;
}
6 数据收发
1 read/write
socket的网络通信,其利用的是文件描述符(符合Linux的设计哲学)
2 recv/send 接收/发送
recv 结束
NAMErecv, recvfrom, recvmsg - receive a message from a socketSYNOPSIS#include <sys/types.h>#include <sys/socket.h>recv用于从指定的套接字描述符中接收数据(同read)ssize_t recv(int sockfd, void *buf, size_t len, int flags);@sockfd:指定套接字描述符,即从那个接收输入@buf:指向一块缓存区,用于存储接收到的数据@len:指定要接收的字节数@flags:接收标志位0 默认接收,带阻塞接收如果能接收到数据就接收数据如果不能接收到数据,就一直等待,直到接收到数据MSG_DONTWAIT 不阻塞接收如果能够接收到数据,则接收数据如果不能接收到数据,则直接返回返回值:>0 成功返回实际接收到的字节数0 什么都没有接收到-1 接收失败,并且errno被设置
send 发送
NAMEsend, sendto, sendmsg - send a message on a socketSYNOPSIS#include <sys/types.h>#include <sys/socket.h>send 用于向套接字描述符中发送数据ssize_t send(int sockfd, const void *buf, size_t len, int flags);@sockfd:指定套接字描述符,即发送到那里去@buf:指向要发送的数据@len:要发送的数据大小,单位字节@flags:发送标志位0 阻塞发送MSG_DONTWAIT 非阻塞发送返回值 成功返回实际发送的字节数(>=0)失败返回-1 并且errno被设置
3 recvfrom/sendto
从哪里接收/发送给谁
特点
recvfrom 可以保存是谁发送过来的数据(保存发送者的地址)
sendto 可以指定发送的对象(地址),定向发送
一般用于UDP通信,很少使用在TCP通信中?WHY?
因为TCP面向连接的通信,在通信前就已经要求通信双方建立连接
UDP是非连接的通信,所以他需要指定发送给谁,要保留发送者的地址
recvfrom
NAMErecv, recvfrom, recvmsg - receive a message from a socketSYNOPSIS#include <sys/types.h>#include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);@前面四个参数 同recv@src_addr:指向一个 struct sockaddr缓存区(地址),用于存储对方的地址@addrlen:指向一个 socklen_t缓存区(地址)用于存储对方地址的长度src_addr和addrlen的使用,参考accept函数
sendto
NAMEsend, sendto, sendmsg - send a message on a socketSYNOPSIS#include <sys/types.h>#include <sys/socket.h>ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);@前四个参数 同send@dest_addr:指向一个 struct sockaddr缓存区(地址),表示发送给谁@addrlen:即dest_addr的长度
4 recvmsg/sendmsg
以结构体的形式 发送数据/接收数据
7 关闭套接字
套接字: socket 套接字描述符
服务器:用于监听,看是否有客户端发起连接请求
客户端:用于客户端与服务器的通信接口
close 关闭套接字
shutdown
NAMEshutdown - shut down part of a full-duplex connectionSYNOPSIS#include <sys/socket.h>shutdown用于关闭一个链接通道int shutdown(int sockfd, int how);@sockfd:指定套关闭那个链接通道@how:怎样关闭SHUT_RD 关闭读SHUT_WR 关闭写SHUT_RDWR 关闭读写返回值:成功返回0失败返回-1,并且errno被设置
eg:我们搭建的服务器,只获取客户端的信息,而不用给客户端发送信息
则可以关闭链接套接字的写功能
shutdown(connfd,SHUT_WR); //connfd 就变成了只读
结合已有函数和示例代码,查看流程图
尝试搭建一个TCP服务器
create_tcpserver 创建TCP服务器
1 创建socket套接字 网络通信接口
2 bind 绑定网络应用地址(便于其他应用找到本程序的通信接口)
3 listen 设置监听(内核监听是否有客户端向服务器发起连接请求)
mian
1 创建服务器 create_tcpserver
2 等待客户端的连接请求,并于客户端建立连接 accept的返回值connfd就是一个用来与客户端通信的描述符
(链接套接字描述符)
3 根据需求,编写与客户端的通信
案例:实现Ubuntu与开发板互相通信
点此跳转查看案例源码
相关文章:
第三天:实现网络编程基于tcp/udp协议在Ubuntu与gec6818开发板之间双向通信
互联网地址 每一台设备接入互联网后,都会举报一个唯一的地址编号 IP地址 INTERNET地址 internet地址 :它是协议上的一个逻辑地址 目前来说,我们主要的IP地址有两类 IPV4 IPV6 IPV4 其实就是使用一个32bit整数作为IP IPV6 其实就是使用一…...
【MediaSoup---源码篇】(三)Transport
概述 RTC::Transport是mediasoup中的一个重要概念,它用于在mediasoup与客户端之间传输实时音视频数据。 Transport继承着众多的类,主要用于Transport的整体感知 class Transport : public RTC::Producer::Listener,public RTC::Consumer::Listener,publ…...
爱分析《商业智能最佳实践案例》
近日,国内知名数字化市场研究咨询机构爱分析发布《2023爱分析商业智能最佳实践案例》,此评选活动面向落地商业智能的各行企业和商业智能厂商,以第三方专业视角深入调研,评选出具有参考价值的创新案例。永达汽车集团与数聚股份合作…...
golang:context
context作用 goroutine的退出机制 多个goroutine都是平行的被调度的,多个goroutine如何协调工作涉及通信、同步、通知和退出 通信:goroutine之间的通信同步chan通道 同步:不带缓冲的chan提供了一个天然的同步等待机制。通过WaitGroup也可以…...
探讨代理IP与Socks5代理在跨界电商中的网络安全应用
在数字化时代,跨界电商已经成为了商业世界中的一大趋势。然而,跨越国界的电商活动也伴随着网络安全挑战。本文将讨论如何利用代理IP和Socks5代理技术来提高跨界电商中的网络安全,同时也探讨了与游戏相关的爬虫应用。 1. 代理IP和Socks5代理的…...
Guava Cache介绍-面试用
一、Guava Cache简介 1、简介 Guava Cache是本地缓存,数据读写都在一个进程内,相对于分布式缓存redis,不需要网络传输的过程,访问速度很快,同时也受到 JVM 内存的制约,无法在数据量较多的场景下使用。 基…...
ARM 汇编指令作业(求公约数、for循环实现1-100之间和、从SVC模式切换到user模式简单写法)
1、求两个数最大公约数 .text .globl _start_start:mov r0, #9mov r1, #15 Loop: 循环cmp r0,r1 比较r0和r1的大小beq stop 当r0和r1相等时,跳到stop标签subhi r0,r0,r1 r0-r1>0 时,证明r0>r1,将r0-r1的值赋给r0&…...
Go - 【字符串,数组,哈希表】常用操作
一. 字符串 字符串长度: s : "hello" l : len(s) fmt.Println(l) // 输出 5遍历字符串: s : "hello" for i, c : range s {fmt.Printf("%d:%c ", i, c) } // 输出:0:h 1:e 2:l 3:l 4:ofor i : 0; i < le…...
vue 普通组件的 局部注册
vue 普通组件的 注册 11 Vue2_3入门到实战-配套资料\01-随堂代码素材\day03\素材\00-准备代码\小兔鲜首页静态页\src...
医疗虚拟仿真和虚拟现实有什么区别?哪个更好?
随着我们在仿真教育中越来越多地使用新技术,区分虚拟模式的类型很重要。虚拟仿真是一个统称,用来概括术语来描述各种基于仿真的体验,从基于屏幕的平台到沉浸式虚拟现实。然而,各虚拟平台在保真度、沉浸感和临场感的水平上有很大差…...
【.net core】yisha框架使用nginx代理swagger接口无法访问问题
后端代码配置 #在StartUp.cs文件中Configure方法中增加以下代码 app.UseSwagger(c >{//代理路径访问c.PreSerializeFilters.Add((doc, item) >{//根据代理服务器提供的协议、地址和路由,生成api文档服务地址doc.Servers new List<OpenApiServer>{ new…...
uniapp录音功能和音频播放功能制作
录音功能 在 UniApp 中,你可以使用 uni.getRecorderManager() 方法来创建一个录音管理器实例,从而实现录音功能。 以下是一个示例,演示了如何在 UniApp 中使用 uni.getRecorderManager() 实现录音功能: // 在需要录音的页面或组…...
服务器数据恢复-LINUX操作系统下各文件系统误删除/格式化数据的恢复方案
服务器数据恢复环境: 基于EXT2/EXT3/EXT4/Reiserfs/Xfs文件系统的Linux操作系统。 服务器故障: LINUX操作系统下误删除/格式化数据。 服务器数据恢复过程: 1、首先会检测服务器是否存在硬件故障,如果检测出硬件故障,交…...
python/C++二分查找库函数(lower_bound() 、upper_bound,bisect_left,bisect_right)
二分查找是一种经典的搜索算法,广泛应用于有序数据集中。它允许在大型数据集中高效地查找目标元素,减少了搜索的时间复杂度。本文将介绍在 C 和 Python 中内置的二分查找函数,让二分查找变得更加容易。 c lower_bound() 、upper_bound 定义…...
爬虫 — App 爬虫(二)
目录 一、Appium介绍二、node.js 安装三、Java 的 SDK 安装以及配置1、安装步骤2、配置环境变量 四、安卓环境的配置1、配置环境变量 五、Appium 安装1、安装2、打开 APP3、使用 六、Appium 使用1、定位数据(方法一,不常用)2、定位数据&#…...
汽车电子相关术语
SOA SOA(Service-Oriented Architecture,面向服务的架构)是一种在计算机环境中设计、开发、部署和管理离散模型的方法。是由Garnter1996年提出的概念,将应用程序的不同功能单元(称为服务)进行拆分…...
Python 找出最大数
"""在输入的三个数中找出最大知识点:1、条件嵌套语句if/else2.字符串分割函数split()3、列表元素索引4、数据类型转换举一反三:1、如何控制只能输入三个数,否则重新输入2、如何避免输入无效字母"""# 定义一个变…...
Spring Security 用了那么久,你对它有整体把控吗?
文章目录 1.Servlet Filter:守门人的角色2.DelegatingFilterProxy:桥接 Servlet 和 Spring 的神器3.FilterChainProxy:Spring Security 过滤器链的管家3.SecurityFilterChain:Security 过滤器的串绳4.Spring Security 中的过滤器机…...
vue+minio实现文件上传操作
vueminio实现文件上传操作 minio文件上传vueminio实现文件上传操作 minio文件上传 minio文件上传有两种方法: 第一种是通过ak,sk,调用minio的sdk putObject进行文件上传;该方法支持go,java,js等各种语言&…...
使用JavaScript实现无限滚动的方法
前言 在网页设计中,无限滚动是一种常见的交互方式,用户可持续地加载更多内容而无需刷新页面,提高用户体验。本文将介绍如何运用JavaScript实现无限滚动的效果,使网页能够自动加载更多数据,减轻用户加载新页的负担&…...
html学习综合案例1
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>个人简介</title> </head> <body>…...
神经节苷脂抗体——博迈伦
神经节苷脂抗体是指人体免疫系统中产生的一类抗体,其主要作用是攻击神经节苷脂抗原物质。神经节苷脂是一种存在于神经细胞表面的重要分子,参与了神经细胞间的信号传导和细胞黏附等重要功能。正常情况下,人体免疫系统不会对神经节苷脂产生抗体…...
【Unity】简单的深度虚化shader
【Unity】简单的深度虚化shader 实现效果 可以用于对地图场景边界的白模处理 实现方法 1.关键方法 UnityObjectToClipPos:将物体坐标转换为屏幕坐标 LinearEyeDepth:将屏幕坐标中的z值转换为实际的深度值 saturate:将值规范到0~1之间&a…...
启动 React APP 后经历了哪些过程
本文作者为 360 奇舞团前端开发工程师 前言 本文中使用的React版本为18,在摘取代码的过程中删减了部分代码,具体以源代码为准。 在React 18里,通过ReactDOM.createRoot创建根节点。并且通过调用原型链上的render来渲染。 本文主要是从以下两个…...
带自动采集小说网站源码 小说听书网站源码 小说网站源码 带教程
PTCMS可听书可下载的小说站源码 带自动采集和搭建视频教程 必装环境:Nginx(apache.iis也可),mysql,php5.6,memcached php5.6安装扩展memcache新建站点,注意新建时,PHP版本必须选择PHP5.6 安装教程 1.上传网站文件到网站目录&…...
MySQL学习笔记2
MySQL glibc版本安装: 下载相应的安装包。 学会查看mysql的官方文档: 1) 2)点击“Reference Manual”按钮: 3)选择5.7版本: 4)点击Installing MySQL on Unix/Linux Using Generic …...
【python爬虫】—星巴克产品
文章目录 需求爬取星巴克产品以及图片,星巴克菜单 python爬虫爬取结果 需求 爬取星巴克产品以及图片,星巴克菜单 网页分析: 首先,需要分析星巴克官方网站的结构,了解菜单栏的位置、布局以及菜单项的标签或类名等信息…...
算法 矩阵最长递增路径-(递归回溯+动态规划)
牛客网: BM61 求矩阵的最长递增路径 解题思路: 1. 遍历二维矩阵每个位置,max求出所有位置分别为终点时的最长路径 2. 求某个位置为终点的最长路径时,使用动态规划dp对已经计算出的位置进行记录 3. 处理某个位置的最长路径时,如果dp[i][j]位…...
四、数学建模之图与网络模型
1.定义 2.例题及软件代码求解 一、定义 1.图和网络是相关概念 (1)图(Graph):图是数学和计算机科学中的一个抽象概念,它由一组节点(顶点)和连接这些节点的边组成。图可以是有向的&…...
php在header增加key,sign,timestamp,实现鉴权
在PHP中,您可以通过在HTTP请求的Header中增加Key、Sign和Timestamp等信息来进行安全性鉴权。 以下是一种基本的思路和示例,用于说明如何实现这种鉴权机制: 生成Key和Sign: 服务端和客户端之间共享一个密钥(Key&#x…...
手机网站建设多少钱一个/优化网络搜索引擎
Android Support v4: 这个包是为了照顾1.6及更高版本而设计的,这个包是使用最广泛的,eclipse新建工程时,都默认带有了。 Android Support v7: 这个包是为了考虑照顾2.1及以上版本而设计的,但不包含更低,故如果不考虑…...
北京餐饮培训网站建设/端口扫描站长工具
供应商管理是一个术语,描述企业管理其供应商的过程,这些供应商又被称作供货商。供应商管理包括选择供应商、谈判合同、控制成本、减少与供应商有关的风险以及确保服务交付等活动。 企业使用的供应商因组织性质的不同而有很大不同,可能包括不…...
苍南网站建设/广州网站建设正规公司
android系统的默认对话框是黑色背景,白色边框的样式,对于android系统来说是相当漂亮的,可是与自己的项目风格不搭,所以只好想办法重写他的样式了,当然dialog是支持样式重写的 使用new Dialog(context, style).setConte…...
广州定制网站建设方案书/免费的关键词挖掘工具
1、Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcache相比一个最大的区别。 2、Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而Memcache只是简单的K/V缓存。 他们的扩展都需要做集群;实现方…...
建设手机移动网站/顾问式营销
确保基本路由器安全的方法是配置口令。强口令是控制安全访问路由器的最基本要素。因此,应该始终配置强口令。 有关口令的最佳做法包括下列几项:请勿将口令记在明显的地方,例如您的办公桌或显示器上。避免使用字典中可查到的单词、姓名、电话号…...
由于网站开发功能不完善/网站seo优化方法
第一种在http://www.jboss.org/tools/download/stable/3_0_GA.html网页上下载需要的插件,http://downloads.sourceforge.net/jboss/FreeMarkerIDE-1.0.2.v200910211631N-H194-GA.zip,解压,把features和plugins的东东加到elispe的features和pl…...