linux并发服务器 —— linux网络编程(七)

news2025/1/10 14:08:42

网络结构模式

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 - ipv6
            AF_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函数得到的fd
        addr - 需要绑定的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 IPV4
        AF - INET6 IPV6
    src - 需要转换的点分十进制的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*)&num;
    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通信流程

UDPTCP
用户数据包协议传输控制协议
面向无连接面向连接
可以单播,多播,广播只能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++){
            // 从数组中找到可用的sockInfo
            if(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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式锁之redis实现

docker安装redis 拉取镜像 docker pull redis:6.2.6 查看镜像 启动容器并挂载目录 需要挂在的data和redis.conf自行创建即可 docker run --restart always -d -v /usr/local/docker/redis/redis.conf:/usr/local/etc/redis/redis.conf -v /usr/local/docker/redis/data:/dat…

leetcode986. 区间列表的交集(java)

区间列表的交集 题目描述贪心 - 合并区间代码演示 题目描述 难度 - 中等 leetcode986. 区间列表的交集 给定两个由一些 闭区间 组成的列表&#xff0c;firstList 和 secondList &#xff0c;其中 firstList[i] [starti, endi] 而 secondList[j] [startj, endj] 。每个区间列表…

【数学建模竞赛】超详细Matlab二维三维图形绘制

二维图像绘制 绘制曲线图 g 是表示绿色 b--o是表示蓝色/虚线/o标记 c*是表示蓝绿色(cyan)/*标记 ‘MakerIndices,1:5:length(y) 每五个点取点&#xff08;设置标记密度&#xff09; 特殊符号的输入 序号 需求 函数字符结构 示例 1 上角标 ^{ } title( $ a…

Arthas教程 - 命令篇 (二)

目录 一、Attach 黏附一个进程 1.1 准备代码 1.2 启动Demo 1.3 启动arthas 1.4 通过浏览器连接arthas 二、常用命令 2.1 dashboard 仪表盘 2.2 cls 清屏 2.3 thread 线程 2.4 jad 反编译类 2.5 watch 监视 2.6 退出arthas 三、基础命令 3.1 help 3.2 cat 3.3 …

小米新机代号“Manet”:搭载高通8 Gen 3 处理器 + 金属中框设计

根据数码闲聊站和体验more的消息爆料&#xff0c;小米Redmi K70 Pro被代号为“Manet”&#xff0c;将搭载高通SM8650处理器&#xff0c;这是骁龙8 Gen 3移动平台的一部分。该处理器基于台积电N4P工艺制程打造&#xff0c;具有强大的性能表现。 CPU包含1*3.19GHz X45*2.96GHz A7…

Python Opencv实践 - 矩形轮廓绘制(直边矩形,最小外接矩形)

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/stars.png") plt.imshow(img[:,:,::-1])img_gray cv.cvtColor(img, cv.COLOR_BGR2GRAY) #通过cv.threshold转换为二值图 ret,thresh cv.threshold(img_gray,…

Error from server (NotFound): pods “nginx-57d84f57dc-b866m“ not found

原因&#xff1a;机房断电&#xff0c;导致服务重启 [rootmaster1 logs]# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-57d84f57dc-57fkf 1/1 Running 0 75s [rootmaster1 logs]# kubectl logs -f nginx-5…

nginx使用详解

文章目录 一、前言二、nginx使用详解2.1、nginx特点2.2 静态文件处理2.3 反向代理2.4 负载均衡2.5 高级用法2.5.1 正则表达式匹配2.5.2 重定向 三、总结 一、前言 本文将详细介绍nginx的各个功能使用&#xff0c;主要包括 二、nginx使用详解 2.1、nginx特点 高性能&#xff…

【JVM】垃圾收集算法

文章目录 分代收集理论标记-清除算法标记-复制算法标记-整理算法 分代收集理论 当前商业虚拟机的垃圾收集器&#xff0c;大多数都遵循了“分代收集”&#xff08;Generational Collection&#xff09;[1]的理论进 行设计&#xff0c;分代收集名为理论&#xff0c;实质是一套符…

C#循环定时上传数据,失败重传解决方案,数据库标识

有些时候我们需要定时的上传一些数据库的数据&#xff0c;在数据不完整的情况下可能上传失败&#xff0c;上传失败后我们需要定时在重新上传失败的数据&#xff0c;该怎么合理的制定解决方案呢&#xff1f;下面一起看一下&#xff1a; 当然本篇文章只是提供一个思路&#xff0…

windows系统bat脚本调用powershell脚本

前言 项目上有些项目既使用了bat脚本&#xff0c;又使用了powershell脚本&#xff1b; 需要两种脚本配合使用&#xff1b; bat调用powershell 不隐藏窗口运行 bat脚本代码&#xff1a;执行当前路径下的1.ps1脚本文件 start powershell .\1.ps1pause powershell脚本代码&…

025: vue父子组件中传递方法控制:$emit,$refs,$parent,$children

第025个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

prometheus通过blackbox-exporter监控web站点证书

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

如何在面试中处理竞争与压力

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

WebSocket与SSE区别

一&#xff0c;websocket WebSocket是HTML5下一种新的协议&#xff08;websocket协议本质上是一个基于tcp的协议&#xff09; 它实现了浏览器与服务器全双工通信&#xff0c;能更好的节省服务器资源和带宽并达到实时通讯的目的 Websocket是一个持久化的协议 websocket的原理 …

算法笔记:二叉树

1 基本二叉树 二叉树是一种树形数据结构&#xff0c;其中每个节点最多有两个子节点&#xff0c;通常称为“左子节点”和“右子节点”。 二叉树的根是唯一没有父节点的节点&#xff0c;而所有其他节点都有一个父节点和零个或两个子节点。 1.1 基础术语 节点&#xff08;Node&…

服务运营 | MSOR文章精选:远程医疗服务中的统计与运筹(二)

作者信息&#xff1a;王畅&#xff0c;陈盈鑫 编者按 在上一期中&#xff0c;我们分享了与远程医疗中运营管理问题相关的两篇文章。其一发表在《Stochastic Systems》&#xff0c;旨在使用排队论与流体近似的方法解决远程医疗中资源配置的问题&#xff1b;其二发表在《Managem…

R_I相关指令函数(SMART PLC梯形图代码)

大部分小型PLC可能并没有R_I(浮点数转单字)指令&#xff0c;这篇博客我们介绍简单实用的一些转换FC,这些FC其实并不复杂&#xff0c;但是可以大大简化我们的代码量&#xff0c;使代码阅读起来更简介明了。SMART PLC的ABS()指令请查看下面文章链接&#xff1a; PLC绝对值指令AB…

04 Linux补充|C/C++

目录 Linux补充 C语⾔ C语言中puts和printf的区别&#xff1f; Linux补充 (1)ubuntu安装ssh服务端openssh-server命令&#xff1a; ubuntu安装后默认只有ssh客户端&#xff0c;只能去连其它ssh服务器&#xff1b;其它客户端想要连接这个ubuntu系统&#xff0c;需要安装部署…

LLM大模型推理加速 vLLM

参考&#xff1a; https://github.com/vllm-project/vllm https://zhuanlan.zhihu.com/p/645732302 https://vllm.readthedocs.io/en/latest/getting_started/quickstart.html ##文档 加速原理&#xff1a; PagedAttention&#xff0c;主要是利用kv缓存 使用&#xff1a; #…