网络编程(学习)2024.8.30

news2024/11/16 17:44:06

目录

IO多路复用  select、poll、epoll

IO多路复用机制 

一.select

1.函数

2.流程

3.案例使用select创建全双工客户端

4.并发服务器

5.案例使用select创建全双工服务端

二.poll

1.函数

2.流程

3.案例使用poll创建全双工客户端

4.案例使用poll创建全双工服务端

三、epoll

1.流程

2.案例使用epoll创建全双工服务端

select,poll和epoll的特点:

1.select特点

2.poll特点

3.epoll特点

IO多路复用  select、poll、epoll

案例分析:键盘鼠标事件

同时对键盘和鼠标进行监听,当敲击键盘按下回车,就打印键盘输入的东西,动鼠标就要打印鼠标写入的内容。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

#define N 64
int main(int argc, char const *argv[])
{
    int mouse = open("/dev/input/mouse0", O_RDONLY);
    if (mouse < 0)
    {
        perror("open失败");
        return -1;
    }
    char buf[N];
    while (1)
    {
        memset(buf, 0, N);
        gets(buf);
        printf("buf:%s\n", buf);
        int ret = read(mouse, buf, N);
        if (ret < 0)
        {
            perror("read失败");
            return -1;
        }
        else
        {
            printf("mouse:%s\n", buf);
        }
    }
}

IO多路复用机制 

使用I/O多路复用技术。其基本思想是:

1.先构造一张有关描述符的表,然后调用一个函数。
2.当这些文件描述符中的一个或多个已准备好进行I/O时函数才返回。
3.函数返回时告诉进程哪个描述符已就绪,可以进行I/O操作。

一.select

1.函数

#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

 int select(int nfds(轮询的文件描述符个数), fd_set *readfds(读文件), fd_set *writefds(写文件),fd_set *exceptfds(异常文件), struct timeval *timeout(超时时长));

一般写:select(int nfds,fd_set *readfds,NULL,NULL,NULL);

void FD_CLR(int fd, fd_set *set);        //将某一文件描述符在表里去除
int  FD_ISSET(int fd, fd_set *set);        //判断某一文件描述符是否在表里
void FD_SET(int fd, fd_set *set);        //将某一文件描述符放入表中
void FD_ZERO(fd_set *set);        //将表置零

2.流程

第一步:建表初始化
第二步:填表
第三步:监听表
第四步:判断,操作

e26c46e3e64c4269ba46d4f5e45ce5d6.png

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>

#define N 64
int main(int argc, char const *argv[])
{
    int mouse = open("/dev/input/mouse0", O_RDONLY);
    if (mouse < 0)
    {
        perror("open失败");
        return -1;
    }
    char buf[N];

    // 第一步:建表初始化
    fd_set readfds, tempfds;
    FD_ZERO(&readfds);
    // 第二步:填表
    FD_SET(0, &readfds);
    FD_SET(mouse, &readfds);
    // 第三步:监听表
    while (1)
    {
        memset(buf, 0, N);
        temphfds = readfds;
        int ret = select(4, &tempfds, NULL, NULL, NULL);
        // 第四步:判断,操作
        if (ret == -1)
        {
            perror("select失败");
            return -1;
        }
        if (FD_ISSET(0, &tempfds))
        {
            gets(buf);
            printf("buf:%s\n", buf);
        }
        if (FD_ISSET(mouse, &tempfds))
        {
            int n = read(mouse, buf, N);
            if (n < 0)
            {
                perror("read失败");
                return -1;
            }
            else
            {
                printf("mouse:%s\n", buf);
            }
        }
    }

    return 0;
}

3.案例使用select创建全双工客户端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <errno.h>

int main(int argc, char const *argv[])
{
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("sorkfd:%d\n", sockfd);

    // 2.连接
    unsigned short post = 0;
    char ip[15];
    printf("请输入ip地址");
    scanf("%s", ip);
    getchar();
    printf("请输入端口号");
    scanf("%hd", &post);
    getchar();
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(post);
    saddr.sin_addr.s_addr = inet_addr(ip);
    socklen_t addrlen = sizeof(saddr);
    if (connect(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("connect失败\n");
        return -1;
    }

    // 3.接收
#define N 64
    char buf[N];
    while (1)
    {
        // 第一步:建表初始化
        fd_set readfds, tempfds;
        FD_ZERO(&readfds);
        // 第二步:填表
        FD_SET(0, &readfds);
        FD_SET(sockfd, &readfds);
        // 第三步:监听表
        while (1)
        {
            memset(buf, 0, N);
            tempfds = readfds;
            int ret = select(4, &tempfds, NULL, NULL, NULL);
            // 第四步:判断,操作
            if (ret == -1)
            {
                perror("select失败");
                return -1;
            }
            if (FD_ISSET(0, &tempfds))
            {
                scanf("%s", buf);
                send(sockfd, buf, N, 0);
            }
            if (FD_ISSET(sockfd, &tempfds))
            {
                int ret = recv(sockfd, buf, N, 0);
                printf("服务端:%s\n", buf);
            }
        }
    }
    close(sockfd);
    return 0;
}

4.并发服务器

可以同时接收多个客户端的连接

5.案例使用select创建全双工服务端

sockfd只要创建并监听listen,就可以接收连接请求,即只要sockfd的读缓冲区可读,就可以创建连接。
客户端的连接请求会发给sockfd,如果可以建立连接的话,会在sockfd的缓冲区内保存
accept其实就是去sockfd的缓冲区里取连接

select创建并发服务器过程

创建并发服务器
创建连接      accept  --> sockfd
发送消息         gets    --> 0
接收          recv    --> 所有已连接的acceptfd

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>

#define N 64
char buf[N];
#define ERR_MSG(msg)                           \
    do                                         \
    {                                          \
        fprintf(stderr, "line:%d ", __LINE__); \
        perror(msg);                           \
    } while (0)

int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("用法:<port>\n");
        return -1;
    }
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("sorkfd:%d\n", sockfd);
    // 2.bind绑定IP和Port端口号
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    // saddr.sin_addr.s_addr = inet_addr("192.168.50.213");
    socklen_t addrlen = sizeof(saddr);
#if 0
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
#else
    saddr.sin_addr.s_addr = INADDR_ANY;
#endif

    if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        ERR_MSG("bind失败");
        return -1;
    }
    printf("bind成功\n");

    // 3.监听listen将主动套接字变为被动套接字
    if (listen(sockfd, 7) < 0)
    {
        ERR_MSG("lisren失败");
        return -1;
    }
    printf("listen成功\n");

    // 第一步:建表初始化
    fd_set readfds, tempfds;
    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);
    FD_SET(0, &readfds);
    int max = sockfd;

    while (1)
    {
        memset(buf, 0, N);
        tempfds = readfds;
        int ret = select(max + 1, &tempfds, NULL, NULL, NULL);
        if (ret == -1)
        {
            perror("select失败");
            return -1;
        }
        if (FD_ISSET(sockfd, &tempfds))
        {
            // 4.accept阻塞等待链接
            int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &addrlen);
            if (acceptfd < 0)
            {
                ERR_MSG("accept失败\n");
                return -1;
            }
            printf("acceptfd:%d\n", acceptfd);
            printf("客户端ip:%s\t 端口号:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
            FD_SET(acceptfd, &readfds);
            if (max < acceptfd)
            {
                max = acceptfd;
            }
        }
        // 5.发送
        else if (FD_ISSET(0, &tempfds))
        {
            scanf("%s", buf);
            for (int i = 4; i <= max; i++)
            {
                if (FD_ISSET(i, &readfds))
                {
                    send(i, buf, N, 0);
                }
            }
        }
        // 6.接收
        for (int n = 4; n <= max; n++)
        {
            if (FD_ISSET(n, &tempfds))
            {
                int ret = recv(n, buf, N, 0);
                if (ret < 0)
                {
                    perror("recv失败");
                    return -1;
                }
                else if (ret > 0)
                {
                    printf("客户端:%s\n", buf);
                }
                else
                {
                    printf("客户端acceptfd:%d退出\n", n);
                    FD_CLR(n, &readfds);
                    close(n);
                    while (!FD_ISSET(max, &readfds))
                    {
                        max--;
                    }
                }
            }
        }
    }
    close(sockfd);
    return 0;
}

二.poll

1.函数

#include <poll.h>

int poll(suct trpollfd *fds, nfds_t nfds, int timeout);

参数:

        fds:创建的pollfd结构体类型的数组

        nfds:数组的大小

        timeout:超时检测的时间,一般不用的话设置为-1

返回值:

        成功:0

        失败:-1

struct pollfd {
        int   fd;        //第一个成员变量 fd是向poll说明要监听哪个文件描述符
        short events;        //第二个成员变量 events 是向poll说明要对这个文件描述符的哪种事件进行监听,一般设置为POLLIN
        short revents;         //第三个成员变量 revents 是poll函数自动生成,当fd发生了events事件时,poll函数会将events(POLLIN)写入revents
};

2.流程

3.案例使用poll创建全双工客户端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>

int main(int argc, char const *argv[])
{
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("sorkfd:%d\n", sockfd);

    // 2.连接
    unsigned short post = 0;
    char ip[15];
    printf("请输入ip地址");
    scanf("%s", ip);
    getchar();
    printf("请输入端口号");
    scanf("%hd", &post);
    getchar();
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(post);
    saddr.sin_addr.s_addr = inet_addr(ip);
    socklen_t addrlen = sizeof(saddr);
    if (connect(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("connect失败\n");
        return -1;
    }

    // 3.接收
#define N 64
    char buf[N];
    while (1)
    {
        // 第一步:建表初始化
        struct pollfd fds[2];

        // 第二步:填表
        fds[0].fd = 0;
        fds[0].events = POLLIN;
        fds[1].fd = sockfd;
        fds[1].events = POLLIN;

        // 第三步:监听表
        while (1)
        {
            memset(buf, 0, N);
            poll(fds, 2, -1);
            // 第四步:判断,操作
            // if (ret == -1)
            // {
            //     perror("select失败");
            //     return -1;
            // }
            for (int i = 0; i <= 1; i++)
            {
                if (fds[i].revents == POLLIN)
                {
                    if (i == 0)
                    {
                        scanf("%s", buf);
                        send(sockfd, buf, N, 0);
                    }
                    if (i == 1)
                    {
                        int ret = recv(sockfd, buf, N, 0);
                        if (ret < 0)
                        {
                            perror("recv失败");
                            return -1;
                        }
                        else
                        {
                            printf("服务端:%s\n", buf);
                        }
                    }
                }
            }
        }
    }
    close(sockfd);
    return 0;
}

4.案例使用poll创建全双工服务端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <poll.h>

#define N 64
char buf[N];
#define ERR_MSG(msg)                           \
    do                                         \
    {                                          \
        fprintf(stderr, "line:%d ", __LINE__); \
        perror(msg);                           \
    } while (0)

int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("用法:<port>\n");
        return -1;
    }
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("sorkfd:%d\n", sockfd);
    // 2.bind绑定IP和Port端口号
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("192.168.50.213");
    socklen_t addrlen = sizeof(saddr);
    // #if 0
    //     saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    // #else
    //     saddr.sin_addr.s_addr = INADDR_ANY;
    // #endif

    if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        ERR_MSG("bind失败");
        close(sockfd);
        return -1;
    }
    printf("bind成功\n");

    // 3.监听listen将主动套接字变为被动套接字
    if (listen(sockfd, 7) < 0)
    {
        ERR_MSG("lisren失败");
        close(sockfd);
        return -1;
    }
    printf("listen成功\n");

    // 第一步:建表初始化
    struct pollfd fds[100];
    int last = -1;

    // 第二步:填表
    fds[++last].fd = 0;
    fds[last].events = POLLIN;
    fds[last].revents = 0;
    fds[++last].fd = sockfd;
    fds[last].events = POLLIN;
    fds[last].revents = 0;

    while (1)
    {
        memset(buf, 0, N);
        int po = poll(fds, last + 1, -1);
        if (po == -1)
        {
            perror("select失败");
            close(sockfd);
            return -1;
        }
        for (int i = 0; i <= last; i++)
        {
            if (fds[i].revents == POLLIN)
            {
                if (fds[i].fd == sockfd)
                {
                    // 4.accept阻塞等待链接
                    int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &addrlen);
                    if (acceptfd < 0)
                    {
                        ERR_MSG("accept失败\n");
                        return -1;
                    }
                    printf("acceptfd:%d\n", acceptfd);
                    printf("客户端ip:%s\t 端口号:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
                    fds[++last].fd = acceptfd;
                    fds[last].events = POLLIN;
                    fds[last].revents = 0;
                }
                else if (fds[i].fd == 0)
                {
                    scanf("%s", buf);
                    for (int j = 2; j <= last; j++)
                    {
                        send(fds[j].fd, buf, N, 0);
                    }
                }
                else
                {
                    int ret = recv(fds[i].fd, buf, N, 0);
                    if (ret < 0)
                    {
                        perror("recv失败");
                        close(sockfd);
                        return -1;
                    }
                    else if (ret > 0)
                    {
                        printf("客户端%s:%s\n", inet_ntoa(caddr.sin_addr), buf);
                    }
                    else
                    {
                        printf("客户端acceptfd:%d退出\n", fds[i].fd);
                        close(fds[i].fd);
                        fds[i] = fds[last];
                        last--;
                    }
                }
            }
        }
    }
    close(sockfd);
    return 0;
}

三、epoll

1.流程

2.案例使用epoll创建全双工服务端

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/epoll.h>
int main(int argc, char const *argv[])
{
    if (argc != 2)
    {
        printf("usage: <port>\n");
        return -1;
    }

    // 1.创建套接字-->tcp  流式套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("sockfd:%d\n", sockfd);
    // 2.绑定IP和端口号
    // 填充通信结构体
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;            // 选定ipv4协议族
    saddr.sin_port = htons(atoi(argv[1])); // 绑定端口
    // saddr.sin_addr.s_addr = inet_addr(argv[1]); // 绑定ip地址
#if 1
    saddr.sin_addr.s_addr = INADDR_ANY; // 绑定ip地址
#else
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0"); // 绑定ip地址
#endif
    socklen_t len = sizeof(saddr);
    // 绑定
    if (bind(sockfd, (struct sockaddr *)&saddr, len) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok\n");
    // 3.启动监听 将主动套接字变成被动套接字
    if (listen(sockfd, 8) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok\n");

    // 1.创建红黑树,拿到根节点---》建表
    int epfd = epoll_create(99);
    // 2.将关心的文件描述符挂载到树上---》填表
    struct epoll_event event;
    struct epoll_event events[10];

    event.data.fd = sockfd;
    event.events = EPOLLIN | EPOLLET;
    epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event);
    // 3.去链表中拿事件
    char buf[128];
    while (1)
    {
        int ret = epoll_wait(epfd, events, 10, -1);
        if (ret < 0)
        {
            perror("errr");
            return -1;
        }
        else if (ret == 0)
        {
            printf("nothing \n");
        }
        else
        {
            for (int i = 0; i < ret; i++)
            {

                if (events[i].data.fd == sockfd)
                {
                    int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
                    if (acceptfd < 0)
                    {
                        perror("accept err");
                        return -1;
                    }
                    printf("%d,login\n", acceptfd);
                    event.data.fd = acceptfd;
                    event.events = EPOLLIN | EPOLLET;
                    epoll_ctl(epfd, EPOLL_CTL_ADD, acceptfd, &event);
                }
                else
                {
                    int ret = recv(events[i].data.fd, buf, sizeof(buf), 0);
                    if (ret < 0)
                    {
                        perror("recv err");
                        return -1;
                    }
                    else if (ret > 0)
                    {
                        printf("%d:%s\n", events[i].data.fd, buf);
                    }
                    else
                    {
                        printf("%d exit\n", events[i].data.fd);
                        close(events[i].data.fd);
                        event.data.fd = events[i].data.fd;
                        event.events = EPOLLIN | EPOLLET;
                        epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, &event);
                    }
                }
            }
        }
    }
    return 0;
}

select,poll和epoll的特点:

1.select特点

优点:可跨平台,Linux、macos、windows都可用
      可以监听多个文件描述符
      轻量级

缺点:最大监听1024个文件描述符,最大监听1020个客户端连接
      每次都要进行轮询,消耗CPU
      每次都要拷贝一遍表

2.poll特点

优点:
1、优化了文件描述符的数量,监听的文件描述符数取决于数组的大小,数组大小受内存容量的限制。
2、不需要每次都拷贝一遍表
缺点:
1、需要轮询
2、只能用在UNIX原生系统下,不支持跨平台

3.epoll特点

优点:
1、超高并发,百万级并发
2、不需要轮询,因为有异步通知机制
3、不需要拷贝表
缺点:
    只能跑在Linux

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

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

相关文章

国产统信UOS桌面操作系统安装网络打印机

国产统信UOS桌面操作系统安装网络打印机比较麻烦&#xff0c;本文件记录了一些打印机的安装方法。 厂商机型驱动方式打印情况柯尼卡美能达KONICA MINOLTA bizhub c360i加装驱动正常惠普HP Color LaserJet Pro MFP M479fdw默认驱动正常东芝TOSHIBA e-STUDIO2020AC CSHM14177加装…

九、制作卡牌预制体

文章目录 制作预制体Physic 2D Raycaster 射线检测 Physic 2D Raycaster 一、制作预制体 使用两个空物体作为父子级&#xff0c;分别挂UI 设置图层front、从上到下为1-6 父物体挂在一个Sorting组件&#xff0c;因为卡牌可以制作成为一个整体&#xff0c; 所以在父物体上挂载…

Mac 数据恢复技巧:恢复 Mac 上已删除的文件

尝试过许多 Mac 数据恢复工具&#xff0c;但发现没有一款能达到宣传的效果&#xff1f;我们重点介绍最好的 Mac 数据恢复软件。 没有 Mac 用户愿意担心数据丢失&#xff0c;但您永远不知道什么时候会发生这种情况。无论是意外删除 Mac 上的重要文件、不小心弄湿了 Mac、感染病…

pdf转word格式乱了怎么调整?2024帮助你快速进行pdf格式调整的软件

pdf转word格式乱了怎么调整&#xff1f;2024帮助你快速进行pdf格式调整的软件 将PDF文件转换为Word格式时&#xff0c;可能会遇到格式混乱的问题。这通常是由于PDF文件的复杂排版、字体嵌入、图像和表格布局等因素造成的。不过&#xff0c;有一些软件可以帮助你更好地保持原有…

测开必备知识:线程安全和线程不安全

什么是线程安全 线程安全指的是在多线程环境下&#xff0c;一个对象或者数据结构能够保证在并发访问时依然能够维持其预期的行为&#xff0c;不会出现数据不一致或者其他意外情况。 反之就是线程不安全。 多线程环境下可能产生的问题 当多个线程同时访问共享的资源&#xf…

QT笔记 - QProcess读取外部程序(进程)消息

简要介绍 QProcess可用于在当前程序中启动独立的外部程序(进程)&#xff0c;并进行通讯&#xff0c;通讯原理是通过程序的输入或输出流&#xff0c;即通过c中的printf()和或c的std::cout等。 函数 void QProcess::start(const QString & program, const QStringList &am…

直播美颜SDK开发方案详解:如何打造智能化主播美颜工具?

在竞争激烈的市场环境下&#xff0c;如何通过直播美颜SDK打造智能化的主播美颜工具&#xff0c;已成为技术开发者和产品经理们关注的焦点。本篇文章将从核心技术、开发流程和优化策略等方面&#xff0c;详细解析如何构建一款智能化的主播美颜工具。 一、核心技术解析 1.人脸识…

第10讲 后端2

主要目标&#xff1a;理解滑动窗口法、位姿图优化、带IMU紧耦合的优化、掌握g2o位姿图。 第9讲介绍了以为BA为主的图优化。BA能精确优化每个相机位姿与特征点位置。不过在更大的场景中&#xff0c;大量特征点的存在会严重降低计算效率&#xff0c;导致计算量越来越大&#xff0…

图纸安全管理措施有哪些?这九大措施全方位保护图纸安全

图纸安全管理措施是一个综合性的体系&#xff0c;旨在通过技术手段和管理措施确保图纸的机密性、完整性和可用性。以下是一些关键的图纸安全管理措施&#xff0c;以及软件安企神的应用。 一、保密协议与意识教育 签订保密协议&#xff1a;与所有接触图纸的员工签署保密协议&am…

计算方法——插值法程序实现二(牛顿法)

例题 给出的函数关系表&#xff0c;分别利用牛顿插值法计算的近似值。 0.10.20.30.40.51.1051711.2214031.3498591.4918251.648721 参考代码一&#xff1a;Python代码实现&#xff08;自编码&#xff09; import math """ :difference_quotient差商函数 &quo…

基于AppBuilder自定义组件开发大模型应用

AppBuilder简介&#xff1a; 如果大家不了解AppBuilder的话&#xff0c;可以先到这里了解一下&#xff1a; https://cloud.baidu.com/doc/AppBuilder/s/6lq7s8lli 一句话简介&#xff1a; 千帆AppBuilder&#xff08;以下简称AppBuilder&#xff09;是基于大模型搭建AI原生应…

MySQL进阶篇2

三、SQL优化 3.1 插入数据 批量插入推荐每次在 500 ~ 1000 条数据时进行使用。如果大于1000&#xff0c;可以考虑分批次进行插入。 大批量插入数据(100万、1000万) 主键顺序插入的性能比乱序要高 3.2 主键优化 数据组织方式 页分裂 主键顺序插入 主键乱序插入 页合并 (del…

计算机网络-VRRP工作原理

一、VRRP工作原理 前面我们大概了解了VRRP的一些基础概念&#xff0c;现在开始学习VRRP的技术原理。VRRP的选举及工作步骤&#xff1a; 确定网关地址 选举主备 主设备发送VRRP报文通知Backup设备 主设备响应终端ARP并维持在Master状态 终端正常发送报文到网关进行转发 因为我们…

计算机毕业设计Hadoop+PySpark共享单车预测系统 PyHive 共享单车数据分析可视化大屏 共享单车爬虫 共享单车数据仓库 机器学习 深度学习

《Hadoop共享单车分析与预测系统》开题报告 一、课题背景与意义 1.1 课题背景 随着共享经济的快速发展&#xff0c;共享单车作为一种新型绿色环保的共享经济模式&#xff0c;在全球范围内迅速普及。共享单车通过提供便捷的短途出行服务&#xff0c;有效解决了城市居民出行的…

网络安全服务基础Windows--第9节-DNS部署与安全

域名基础知识 域名是互联⽹上⽤来识别各种实体&#xff08;如服务器、服务、⽹络&#xff09;的可读名称。它是⼀种⽅便记忆的地址&#xff0c;⽤于代替IP地址&#xff0c;因为IP地址由数字组成&#xff0c;不容易记忆。域名通过⼀种层级结构的系统组织起来&#xff0c;从最⼀ …

以人口金字塔图为例,在线绘制左右双侧堆叠条形图

导读&#xff1a; 人口金字塔&#xff08;population pyramids&#xff09;用于展示一个特定人口的年龄和性别分布。本质上是一种水平条形图。左侧是男性的数据&#xff0c;右侧是女性的数据。 Proc Natl Acad Sci U S A.文章《Demographic change and assimilation in the ea…

电脑实时监控软件分享!一分钟速览,五个好用的实时屏幕监控软件(良心推荐)

"工欲善其事&#xff0c;必先利其器。"在信息化时代&#xff0c;企业管理的高效与安全离不开先进的工具支持。 电脑实时监控软件已是现代企业管理的重要利器&#xff0c;不仅能帮助管理者实时掌握员工的工作状态&#xff0c;还能有效防止数据泄露&#xff0c;确保信…

FLV封装H265

针对FLV格式&#xff0c;目前许多开源项目和常见的视频处理工具和流媒体服务器&#xff0c;仍主要支持H.264视频编码格式&#xff0c;尚未完全兼容H.265。ffmpeg和vlc都不支持H265编码格式的FLV&#xff0c;不知道后续版本会不会支持。RTMP也是用FLV格式传输音视频&#xff0c;…

CPP继承(下)

目录 继承与友元 继承与静态成员 复杂的菱形继承及菱形虚拟继承 单继承 多继承 菱形继承 菱形继承的问题 虚继承 虚拟继承解决数据冗余和二义性的原理 继承的总结和反思 笔试面试题 继承与友元 友元关系不能继承&#xff0c;也就是说基类友元不能访问子类私有和保护…

淘宝扭蛋机小程序开发,吸引更多的消费者

随着互联网科技的快速发展&#xff0c;小程序已经成为了一个必不可少的发展趋势。小程序具有门槛低、曝光度高、方便的优势&#xff0c;能够满足消费者的需求&#xff0c;还可以为企业商家带来更多的影响力&#xff0c;因此&#xff0c;扭蛋机小程序也成为了市场发展的重要力量…