linux并发服务器 —— linux网络编程(七)
网络结构模式
C/S结构 - 客户机/服务器;采用两层结构,服务器负责数据的管理,客户机负责完成与用户的交互;C/S结构中,服务器 - 后台服务,客户机 - 前台功能;
优点
1. 充分发挥客户端PC处理能力,先在客户端处理再提交服务器,响应速度快;
2. 操作界面好看,满足个性化需求;
3. 安全性较高,面向固定用户群,程序更注重流程;
缺点
1. 需要安装专用的客户端软件;
2. 对客户端的操作系统有限制,不能跨平台;
B/S结构 - 浏览器/服务器;将系统功能实现的核心部分集中于服务器,简化系统开发,维护;
优点
总体成体低,维护方便,分布性强,开发简单;
缺点
1. 通信开销大,系统和数据的安全性较低;
2. 无法实现个性化的功能要求;
3. 协议固定;
4. 响应速度明显降低;
MAC地址、IP地址、端口
MAC地址
网卡是一块被设计用来允许计算机在计算机网络上进行通讯的计算机硬件,又称为网络透配器或网络接口卡NIC,其拥有 MAC 地址,属于 OS 模型的第 2层。
每个网卡都有一个被称为MAC地址的第一无二的48位串行号(以太网卡/无线网卡);
网卡的功能:
1. 数据封装与解封装
2. 链路管理
3. 数据编译与译码
MAC地址 - 媒体存取控制地址/局域网地址/以太网地址/物理地址/硬件地址
MAC地址是用来确认网络设备位置的地址,由网络设备制造商生产时烧录在网卡中;一台设备可以有多个网卡;
IP地址
IP地址是互联网的协议地址,是IP协议提供的一种统一的地址格式,为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此屏蔽物理地址的差异;
A类IP地址 - 一个字节网络地址,三个字节主机地址;1.0.0.1 - 126.255.255.254;子网掩码255.0.0.0;用于广域网
B类IP地址 - 两个字节网络地址,两个字节主机地址;128.0.0.1 - 191.255.255.254;子网掩码255.255.0.0;用于城际网络
C类IP地址 - 三个字节网络地址,一个字节主机地址;192.0.0.1 - 223.255.255.254;子网掩码255.255.255.0;用于局域网
0.0.0.0 - 当前主机
255.255.255.255 - 当前子网的广播地址
IP地址不能以127开头,127.0.0.1可以代表本机IP地址
子网掩码
子网掩码必须结合IP地址一起使用,用于屏蔽IP地址一部分,区分网络地址和主机地址;
192.168.100.10/24 - IP地址192.168.100.10 , 子网掩码24个1;
端口
设备与外界通讯交流的出口 - 虚拟端口/物理端口;
虚拟端口是逻辑意义上的端口,特指TCP/IP协议中的端口;一个IP地址可以由65536个端口,端口通过端口号标识 0 - 65535;一个计算机中不能出现同样端口号的进程,不用进程号的原因是因为进程号是变化的;0~1023是周知端口,紧密绑定一些特定服务,不能自己设置使用;
1024~49151为注册端口,用户选择安装的一些应用程序
49152~65535 动态分配
网络模型
七层参考模型/osi参考模型
1. 物理层 - 定义物理设备的标准(接口类型、传输速率)
2. 数据链路层 - 提供介质访问、链路管理
3. 网络层 - IP选址、路由选择
4. 传输层 - 建立、管理、维护端到端的连接
5. 会话层 - 建立、管理、维护会话
6. 表示层 - 数据格式转化、数据加密
7. 应用层 - 为应用程序提供服务,用户和网络服务的接口
TCP/IP四层模型
协议
通信双方必须共同遵从的一组约定;三要素:语法、语义、时序,最终体现为在网络上传输的数据包格式;各个层之间的协议不互相影响
应用层协议 - FTP(文件传输)/HTTP(超文本传输协议)/NFS(网络文件协议)
传输层协议 - TCP(传输控制协议)/UDP(用户数据包协议)
网络层协议 - IP(因特网互联协议)/ICMP(因特网控制报文协议)/IGMP(因特网组管理协议)
网络接口层协议 - ARP(地址解析协议)/RARP(反向地址解析协议)
UDP协议
TCP协议
IP协议
以太网帧协议
ARP协议
网络通信的过程
封装 - 上层协议通过封装使用下层协议提供的服务;每层协议在上层数据的基础上加上自己的头部/尾部信息,实现该层的功能;
分用 - 帧到达主机,沿着协议栈自底向上依次传递,各层协议处理本层负责的头部数据,获取信息;
ARP协议 - 通过IP地址查找MAC地址; - 28个字节
RARP协议 - 通过MAC地址查找IP地址;
Socket介绍
套接字 - 对网络中不同主机上的应用进程之间进行双向通信的端点的抽象;一个套接字就是网络上进程通信的一段,提供了应用层进程利用网络协议交换数据的机制;上联应用程序,下联网路协议栈,是应用程序与网络协议进行交互的接口;
通信时其中一个网络应用程序将要传输的一段信息写入它所在主机的 socket 中,该 socket通过与网络接口卡 (NIC)相连的传输介质将这段信息送到另外一台主机的 socket 中,使对方能够接收到这段言息。socket 是由 IP 地址和端口结合的,提供向应用层进程传送数据包的机制。
在linux环境下,用于表示进程间网络通信的特殊文件类型;本质为内核借助缓冲区形成的伪文件;
套接字通信分两部分
服务器端:被动接收连接,一般不主动
客户端:主动向服务器发起连接
socket地址
socket地址是一个结构体 - 封装IP和端口号
sa_family是地址族类型的变量,地址族类型通常与协议族相对应;sa_data存放socket地址值
PF_UNIX - 文件路径名 - 108字节
PF_INET - 6个字节 , 16位端口号,32位IP
PFINET6 - 26个字节 , 16位端口号,32位流标识 ,128位IP,32bit范围ID
为了方便使用提出专用的SOCKET地址:
所有专用socket地址实际使用时都需要转换为通用的socket地址;
socket函数
#inc]ude <sys/types .h>
#incIude <sys/socket .h>
#incTude <arpa/inet .h> // 包含了该头文件上面两个可以省略
int socket(int domain, int type, int protoco1);功能:创建一个套接字参数:domain - 协议族 AF_INET - ipv4 AF_INET6 - ipv6AF_UNIX AF_LOCAL - 本地套接字通信(进程间)type - 通信过程中实现的协议类型SOCK_STREAM - 流式协议SOCK_DGRAM - 报式协议protocol - 具体的协议0 - SOCK_STREAM (TCP)- SOCK_DGRAM (UDP)返回值:成功 - 返回文件描述符,操作的就是内核缓冲区失败 - -1
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);功能:绑定fd和本地的IP/端口参数:sockfd - socket函数得到的fdaddr - 需要绑定的socket地址addrlen - 第二个参数结构体的内存大小
int listen(int sockfd, int backlog);// /proc/sys/net/core/somaxconn功能:监听socket上的连接参数:sockfd - 文件描述符backlog - 未连接和已连接的和的最大值
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);功能:接收客户端连接,默认阻塞,等待客户端连接进来参数:sockfd - 文件描述符addr - 传出参数,记录了连接成功后客户端的地址信息addrlen - 第二个参数的内存大小返回值成功 - 用于通信的文件描述符失败 - -1
int connect(int sockfd, const struct sockaddr *addr , socklen_t addrlen) ;功能:客户端连接服务器参数:sockfd - 用于通信的文件描述符addr - 客户端要连接的服务器的地址信息addtrlen - 第二个参数的内存大小返回值:成功 - 0失败 - -1
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf,size_t count);
字节序
字节序,顾名思义宁节的顺序,就是大于一个宁节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)
字节序分为大端字节序和小端字节序;
大端小端的判断
/*字节序判断 - 大端/小端
*/
#include <iostream>
using namespace std;int main(){union{short value;char byte;}test;test.value = 0x0102;if(test.byte == 1){cout<<"大端存储"<<endl;}else if(test.byte == 2){cout<<"小端存储"<<endl;}else{cout<<"未知"<<endl;}return 0;
}
字节序转换函数
格式化的数据在两台不同字节序的主机之间传递会发生问题;所以需要发送端先转大端,接收端再根据自身情况进行转换;socket提供了封装好的转换函数
s - 转换端口;l - 转换IP
网络通信时,需要将主机字节序转换成网络字节序(大端),另外一段获取到数据以后根据情况将网络字节序转换成主机字节
IP地址转换
将字符串IP转为整数/主机网络字节序转换
#include <arpa/inet.h>
// p - 点分十进制字符串 ; n - 网络字节序的整数
int inet_pton(int af, const char *src, void *dst);af - 地址族AF - INET IPV4AF - INET6 IPV6src - 需要转换的点分十进制的IP字符串dst - 转换后的结果保存在这儿
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);size - 第三个参数的大小(数组大小)返回值 - 转换后的数据地址,和dst一样
#include <iostream>
#include <arpa/inet.h>
#include<cstdio>
using namespace std;// int inet_pton(int af, const char *src, void *dst);// const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);int main(){//字符串转整数char buf[] = "192.168.1.4";unsigned int num = 0;inet_pton(AF_INET , buf , &num);unsigned char* p = (unsigned char*)#cout<<(int)*p<<" "<<(int)*(p+1)<<" "<<(int)*(p+2)<<" "<<(int)*(p+3)<<endl;// 整数转字符串char ip[16] = "";const char* str = inet_ntop(AF_INET , &num , ip , sizeof(ip));cout<<str<<endl;return 0;
}
TCP通信流程
UDP | TCP |
用户数据包协议 | 传输控制协议 |
面向无连接 | 面向连接 |
可以单播,多播,广播 | 只能1v1(单播) |
面向数据报 | 基于字节流 |
不可靠的协议 | 可靠的协议 |
TCP 通信流程
服务器
- 创建有一个用于监听的套接字
- 将监听的文件描述符和本地的IP、端口绑定(IP 端口就是服务器的地址信息)
- 设置监听,监听的fd开始工作
- 阻塞等待,当有客户端发起连接,解除阻塞,接受客户端连接,得到和客户端通信的套接字
- 通信(接受数据/发送数据)
- 通信结束断开连接
客户端
- 创建一个用于通信的套接字
- 连接服务器,需要指定连接服务器的IP/端口
- 连接成功了,发生通信
- 通信结束断开连接
TCP通信实现(服务端/客户端)
// 实现TCP服务器端
#include <iostream>
#include <arpa/inet.h>
#include<cstdio>
#include <unistd.h>
#include <string.h>
using namespace std;int main(){// 1. 创建socket(用于监听)int lfd = socket(AF_INET , SOCK_STREAM , 0);// 2. 绑定struct sockaddr_in saddr;saddr.sin_family = PF_INET;inet_pton(AF_INET , "192.168.93.129" , &saddr.sin_addr.s_addr);saddr.sin_port = htons(9998);bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));// 3. 监听listen(lfd , 8);// 4. 接收客户端连接struct sockaddr_in caddr;socklen_t len = sizeof(caddr); int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);// 输出客户端的信息char client_ip[16];inet_ntop(AF_INET , &caddr.sin_addr.s_addr , client_ip , sizeof(client_ip));unsigned short client_port = ntohs(caddr.sin_port);cout<<"IP:"<<client_ip<<" "<<"PORT: "<<client_port<<endl;// 获取客户端的数据char buf[1024] = {0};len = read(cfd , buf , sizeof(buf));cout<<"服务器读取数据:"<<buf<<endl;// 给客户端发数据const char *str = "hello 647";write(cfd , str , strlen(str));close(lfd);close(cfd);return 0;
}
// TCP通信客户端
#include <iostream>
#include <arpa/inet.h>
#include<cstdio>
#include <unistd.h>
#include <string.h>
using namespace std;int main(){// 1. 创建套接字int fd = socket(AF_INET , SOCK_STREAM , 0);// 2. 连接服务器端struct sockaddr_in caddr;caddr.sin_family = AF_INET;inet_pton(AF_INET , "192.168.93.129" , &caddr.sin_addr.s_addr);caddr.sin_port = htons(9998);connect(fd , (struct sockaddr*)&caddr , sizeof(caddr));// 3. 读写数据const char *str = "hello zry";write(fd , str , strlen(str));char buf[1024] = {0};int len = read(fd , buf , sizeof(buf));cout<<"客户端读取数据:"<<buf<<endl;close(fd);return 0;
}
TCP三次握手
三次握手发生在客户端丽连接,调用connect(),底层会通过TCP协议进行三次握手;
注意:第三次握手可以携带数据
滑动窗口
滑动窗口的大小意味着接收方还有多大的缓冲区可用于接收数据;
滑动窗口的大小会随着发送数据/接收数据而变化;
通信双方都有发送缓冲区和接收缓冲区
mss: 一条数据最大的数据量;
win: 滑动窗口;
TCP四次挥手
发生在断开连接的时候,程序调用close()会使用TCP协议进行四次挥手;
客户端/服务端都可以主动发起/断开连接,谁调用close()就是谁发起的;
注意:发起方FIN请求可以携带数据!!
多进程实现并发服务器
实现TCP通信服务器处理并发的任务,使用多线程或者多进程解决;
1. 一个父进程,多个子进程
2. 父进程负责等待并接收客户端的连接
3. 子进程:完成通信,接收一个客户端请求就创建一个子进程
#include <iostream>
#include <arpa/inet.h>
#include<cstdio>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <wait.h>
#include <errno.h>
using namespace std;void fun(int arg){while(1){int ret = waitpid(-1 , NULL , WNOHANG);if(ret == - 1){break;}else if(ret == 0){break;}else{cout<<"回收到了子进程: "<<ret<<endl;}}
}int main(){// 注册信号捕捉struct sigaction act;act.sa_flags = 0;sigemptyset(&act.sa_mask);act.sa_handler = fun;sigaction(SIGCHLD , &act , NULL);// 创建int lfd = socket(AF_INET , SOCK_STREAM , 0);if(lfd == -1){perror("socket");exit(0);}// 绑定struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(9999);saddr.sin_addr.s_addr = INADDR_ANY;int ret = bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));if(ret == -1){perror("bind");exit(0);}// 监听ret = listen(lfd , 5);if(ret == -1){perror("listen");exit(0);}// 不断循环等待客户端连接while(1){struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);if(cfd == -1){if(errno == EINTR){continue;}perror("accept");exit(0);}// 每一个连接进来,创建子进程与客户端通信pid_t pid = fork();if(pid == 0){// 获取客户端信息char ip[16];inet_ntop(AF_INET , &caddr.sin_addr.s_addr , ip , sizeof(ip));unsigned short port = ntohs(caddr.sin_port);cout<<"IP: "<<ip<<" "<<"port: "<<port<<endl;// 接收客户端发来的数据char buf[1024] = {0};while(1){int len = read(cfd , &buf , sizeof(buf));if(len == -1){perror("read");exit(0);}else if(len > 0){cout<<"读到了数据:"<<buf<<endl;}else{cout<<"已经断开连接了.....";}write(cfd , buf , strlen(buf));}}close(cfd);}close(lfd);return 0;
}
// TCP通信的客户端
#include <iostream>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
int main() {// 1.创建套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd == -1) {perror("socket");exit(-1);}// 2.连接服务器端struct sockaddr_in caddr;caddr.sin_family = AF_INET;inet_pton(AF_INET , "192.168.93.129" , &caddr.sin_addr.s_addr);caddr.sin_port = htons(9999);int ret = connect(fd, (struct sockaddr *)&caddr, sizeof(caddr));if(ret == -1) {perror("connect");exit(-1);}// 3. 通信char recvBuf[1024];int i = 0;while(1) {sprintf(recvBuf, "data : %d\n", i++);// 给服务器端发送数据write(fd, recvBuf, strlen(recvBuf)+1);int len = read(fd, recvBuf, sizeof(recvBuf));if(len == -1) {perror("read");exit(-1);} else if(len > 0) {printf("recv server : %s\n", recvBuf);} else if(len == 0) {// 表示服务器端断开连接printf("server closed...");break;}sleep(1);}// 关闭连接close(fd);return 0;
}
多线程实现并发服务器 - client同多进程并发
#include <iostream>
#include <arpa/inet.h>
#include <cstdio>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
using namespace std;struct sockInfo{int fd;pthread_t tid;struct sockaddr_in addr;
};struct sockInfo sockinfos[128];void *work(void * arg){// 子线程和客户端通信 cfd/客户端信息/线程号// 获取客户端信息struct sockInfo *pinfo = (struct sockInfo *)arg;char ip[16];inet_ntop(AF_INET , &pinfo->addr.sin_addr.s_addr , ip , sizeof(ip));unsigned short port = ntohs(pinfo->addr.sin_port);cout<<"IP: "<<ip<<" "<<"port: "<<port<<endl;// 接收客户端发来的数据char buf[1024] = {0};while(1){int len = read(pinfo->fd , &buf , sizeof(buf));if(len == -1){perror("read");exit(0);}else if(len > 0){cout<<"读到了数据:"<<buf<<endl;}else{cout<<"已经断开连接了.....";break;}write(pinfo->fd , buf , strlen(buf)+1);}close(pinfo->fd);return NULL;
}int main(){// 创建int lfd = socket(AF_INET , SOCK_STREAM , 0);if(lfd == -1){perror("socket");exit(0);}cout<<1;// 绑定struct sockaddr_in saddr;saddr.sin_family = AF_INET;saddr.sin_port = htons(9999);saddr.sin_addr.s_addr = INADDR_ANY;int ret = bind(lfd , (struct sockaddr*)&saddr , sizeof(saddr));if(ret == -1){perror("bind");exit(0);}// 监听ret = listen(lfd , 5);if(ret == -1){perror("listen");exit(0);}// 初始化数据int max = sizeof(sockinfos)/sizeof(sockinfos[0]);for(int i = 0 ; i<max ; i++){bzero(&sockinfos[i] , sizeof(sockinfos[i]));sockinfos[i].fd = -1;sockinfos[i].tid = -1;}// 不断循环等待客户端连接(子线程创建)while(1){struct sockaddr_in caddr;socklen_t len = sizeof(caddr);int cfd = accept(lfd , (struct sockaddr*)&caddr , &len);struct sockInfo *pinfo;for(int i = 0 ; i<max ; i++){// 从数组中找到可用的sockInfoif(sockinfos[i].fd == -1){pinfo = &sockinfos[i];break;}if(i == max - 1){sleep(1);i--;}}pinfo->fd = cfd;memcpy(&pinfo->addr , &caddr , len);// 每一个连接进来,创建子线程与客户端通信pthread_t tid;pthread_create(&pinfo->tid , NULL , work , pinfo);pthread_detach(pinfo->tid);}close(lfd);return 0;
}
相关文章:

linux并发服务器 —— linux网络编程(七)
网络结构模式 C/S结构 - 客户机/服务器;采用两层结构,服务器负责数据的管理,客户机负责完成与用户的交互;C/S结构中,服务器 - 后台服务,客户机 - 前台功能; 优点 1. 充分发挥客户端PC处理能力…...

Java后端开发面试题——企业场景篇
单点登录这块怎么实现的 单点登录的英文名叫做:Single Sign On(简称SSO),只需要登录一次,就可以访问所有信任的应用系统 JWT解决单点登录 用户访问其他系统,会在网关判断token是否有效 如果token无效则会返回401&am…...

TiDB x 安能物流丨打造一栈式物流数据平台
作者:李家林 安能物流数据库团队负责人 本文以安能物流作为案例,探讨了在数字化转型中,企业如何利用 TiDB 分布式数据库来应对复杂的业务需求和挑战。 安能物流作为中国领先的综合型物流集团,需要应对大规模的业务流程ÿ…...

负载均衡算法实现
负载均衡算法实现 负载均衡介绍 负责均衡主要有以下五种方法实现: 1、轮询法 将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载; 2、随机法 通过系统的随机算法&#…...

Flutter 完美的验证码输入框 转载
刚开始看到这个功能的时候一定觉得so easy,开始的时候我也是这么觉得的,这还不简单,然而真正写的时候才发现并没有想象的那么简单。 先上图,不上图你们都不想看,我难啊,到Github: https://gith…...

SpringBoot整合Jpa实现增删改查功能(提供Gitee源码)
前言:在日常开发中,总是撰写一些简单的SQL会非常耗时间,Jpa可以完美的帮我们提高开发的效率,对于常规的SQL不需要我们自己撰写,相对于MyBatis有着更简单易用的功能,但是MyBatis自由度相对于Jpa会更高一些&a…...

微服务[Nacos]
CAP 1)一致性(Consistency) (所有节点在同一时间具有相同的数据) 2)可用性(Availability)(保证每个请求不管成功或者失败都有响应) 3)分区容错(Partition tolerance)(系统中任意信息的丢失或失败不会影响系统的继续运作) 一、虚拟机镜像准备 …...

8K视频来了,8K 视频编辑的最低系统要求
当今 RED、Canon、Ikegami、Sony 等公司的 8K 摄像机以及 8K 电视,许多视频内容制作人和电影制作人正在认真考虑 8K 拍摄、编辑和后期处理,需要什么样的系统来处理如此海量的数据? 中央处理器(CPU) 首先,…...

AsyncContext优雅实现HTTP长轮询接口
一、背景 接到一个需求,实现方案时需要提供一个HTTP接口,接口需要hold住5-8秒,轮询查询数据库,一旦数据库中值有变化,取出变化的值进行处理,处理完成后返回响应。这不就是长轮询吗,如何优雅的实…...

如何制作一个百货小程序
在这个数字化时代,小程序已成为各行各业的必备工具。其中,百货小程序因其便捷性和多功能性,越来越受到人们的青睐。那么,如何制作一个百货小程序呢?下面,我们就详细介绍一下无需编写代码的步骤。 一、进入后…...

【人工智能】—局部搜索算法、爬山法、模拟退火、局部剪枝、遗传算法
文章目录 局部搜索算法内存限制局部搜索算法示例:n-皇后爬山算法随机重启爬山模拟退火算法局部剪枝搜索遗传算法小结 局部搜索算法 在某些规模太大的问题状态空间内,A*往往不够用 问题空间太大了无法访问 f 小于最优的所有状态通常,甚至无法储…...

MATLAB旋转动图的绘制
MATLAB旋转动图的绘制 文章目录 MATLAB旋转动图的绘制1、动图效果2、matlab代码 利用matlab实现三维旋转动图的绘制。 1、动图效果 2、matlab代码 close all clear clcf(x,y,z)(x.^2 (9./4).*y.^2 z.^2 - 1).^3 - x.^2.*z.^3 - (9./80).*y.^2.*z.^3; [x,y,z]meshgrid(linspac…...

算法笔记 近似最近邻查找(Approximate Nearest Neighbor Search,ANN)
1 介绍 精准最近邻搜索中数据维度一般较低,所以会采用穷举搜索,即在数据库中依次计算其中样本与所查询数据之间的距离,抽取出所计算出来的距离最小的样本即为所要查找的最近邻。 当数据量非常大的时候,搜索效率急剧下降。——>…...

uni-app 之 vue语法
uni-app 之 vue语法 image.png --- v-html 字符 --- image.png <template><view><view>{{title}}</view>--- v-html 字符 ---<view>{{title2}}</view><view v-html"title2"></view><view>{{arr}}</view&g…...

Android之RecyclerView仿ViewPage滑动
文章目录 前言一、效果图二、实现步骤1.xml主布局2.所有用到的drawable资源文件3.xml item布局4.adapter适配器5.javabean实体类6.activity使用 总结 前言 我们都知道ViewPageFragment滑动,但是的需求里面已经有了这玩意,但是在Fragment中还要有类似功能…...

【owt-server】AudioSendAdapter分析
owt-server/source/core/rtc_adapter/AudioSendAdapter.cc使用其他线程运行rtprtcpmodule taskrunner分配线程:因此,对rtprtcp的使用都是加了mutex的:首先为音频发送者生成一个随机的ssrc并注册 // SSRCs of this type.std::vector<uint32_t> ssrcs_;发送还要向rtprtc…...

day33 List接口
List实现类 java.util.ArrayList: 底层通过数组保存数据 , 查询快,增删慢 java.util.LinkedList: 底层通过链表保存数据, 查询慢,增删快 如果对操作性能没有特殊要求,我们一般选择ArrayList…...

云原生周刊:Linkerd 发布 v2.14 | 2023.9.4
开源项目推荐 Layerform Layerform 是一个 Terraform 包装器,可帮助工程师使用纯 Terraform 文件构建可重用的基础设施。 为了实现重用,Layerform 引入了层的概念。每层都包含一些基础设施,并且可以堆叠在另一层之上。 除了更易于使用之外…...

CS420 课程笔记 P5 - 内存编辑 数据类型
文章目录 IntroductionData typesBooleansNegative numbers (Signed integers)Floating-point numbers (fractional numbers) Unknown value scansHealth findingFloat finding (Player position hack / Teleport hack) Additional things Introduction 这节课将结束数据类型并…...

oracle报错 ORA-02290: 违反检查约束条件问题
保存数据库信息时,提示违反检查约束条件,如图: org.springframework.dao.DataIntegrityViolationException: ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: ORA-02290: 违反检查约束条件 (MXUSER…...

Prometheus + grafana 的监控平台部署
一、Prometheus安装 tar -zxvf prometheus-2.44.0.linux-amd64.tar.gz -C /opt/module/ sudo chown -R bigdata:bigdata /opt/module/prometheus-2.44.0.linux-amd64 mv /opt/module/prometheus-2.44.0.linux-amd64 /opt/module/prometheus-2.44.0 ln -s /opt/module/promethe…...

npm、yarn、pnpm
一、简介 CommonJS 的出现,使 node 环境下的 JS 代码可以用模块更加细粒度的划分。一个类、一个函数、一个对象、一个配置等等均可以作为模块,这种细粒度的划分,是开发大型应用的基石。 为了解决在开发过程中遇到的常见问题,比如…...

力扣|两数相加
先放题目: 给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,…...

prometheus通过blackbox-exporter监控web站点证书
1 概述 线上站点普遍是https,因此监控https web站点的证书的过期时间,是一个基础性需求。例如,证书过期会导致tls握手失败,进而导致用户无法正常访问web站点。 blackbox-expoter是一个web服务,它暴露了一个接口&#…...

CentOS7 Hadoop3.3.0 安装与配置
一、安装JDK 1、创建文件夹tools和training用于存放压缩包和解压使用,tools存放压缩包,training用于解压后安装jdk和hadoop的路径。 1)回到路径为 / 的位置 cd /2) 创建 tools 和 training mkdir toolsmkdir training3) 进入tools文件夹 …...

2023年9月CDGA/CDGP数据治理认证考试报名,当然弘博创新
据DAMA中国官方网站消息,2023年度第三期DAMA中国CDGA和CDGP认证考试定于2023年9月23日举行。 报名通道现已开启,相关事宜通知如下: 考试科目: 数据治理工程师(CertifiedDataGovernanceAssociate,CDGA) 数据治理专家(CertifiedDataGovernanc…...

Re45:读论文 GPT-1 Improving Language Understanding by Generative Pre-Training
诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名:Improving Language Understanding by Generative Pre-Training 论文下载地址:https://www.mikecaptain.com/resources/pdf/GPT-1.pdf 本文是2018年OpenAI的工作,…...

VB.NET 如何将某个Excel的工作表中复制到另一个的Excel中的工作表中https://bbs.csdn.net/topics/392861034
参考http://share.freesion.com/306372/可以实现直接拷贝指定表 Private Sub Excel复制工作簿()Dim myExcelApp As New Microsoft.Office.Interop.Excel.ApplicationmyExcelApp.Workbooks.Open(System.Environment.CurrentDirectory "\\测试用例.xlsx", Type.Missin…...

深入解析Kotlin类与对象:构造、伴生、单例全面剖析
前言 本篇文章将带您了解Kotlin编程中的重要概念:类及构造函数、访问修饰符、伴生对象和单例模式。就像搭积木一样,我们会逐步揭开这些概念的面纱,让您轻松理解它们的作用和用法。无论您是编程新手还是有经验的开发者,本文都将为…...

JavaScript构造函数
1、构造函数: 是一个函数,是通过new运算符进行调用,生成一个特殊的对象并返回。 function 函数名([参数]){ this.属性名 ‘属性值’ ... this.属性名 function([参数]){ 函数体语句 } } 通常情况下,建议构造函数的首字母大写 …...