linux系统编程-网络-tcp(29)

news2024/11/6 3:16:55

C/S B/S P2p模型

在Linux系统编程中,C/S(Client/Server,客户端/服务器)和B/S(Browser/Server,浏览器/服务器)模型是两种常见的架构模式,用于构建分布式应用程序。它们在设计和实现上有不同的特点和应用场景。以下是它们的对比:

C/S(Client/Server)模型

1. 架构概述
  • 客户端:运行在用户的计算机上,与服务器进行直接的通信。客户端可以是桌面应用程序、移动应用程序或其他类型的应用程序。

  • 服务器:运行在服务器端,提供服务和资源。服务器处理客户端请求并返回响应。

2. 优点
  • 高性能:客户端与服务器之间的通信直接,通常具有较高的效率和响应速度。

  • 丰富的用户界面:客户端可以提供复杂和丰富的用户界面,支持多种交互功能。

  • 离线操作:客户端通常可以在没有网络的情况下运行,并在网络可用时进行数据同步。

3. 缺点
  • 维护复杂:需要维护和更新客户端应用程序的多个版本,可能增加开发和维护的难度。

  • 部署问题:客户端应用程序需要在每个用户的机器上安装,部署过程较为复杂。

  • 平台依赖:客户端可能需要针对不同操作系统开发和测试,增加开发工作量。

4. 应用场景
  • 桌面应用程序(如Office套件)

  • 游戏客户端

  • 专用业务应用程序

5. 示例技术
  • Socket编程:用于客户端与服务器之间的直接通信。

  • RPC远程过程调用:用于客户端调用服务器上的方法。

  • GUI:如Qt、GTK+,用于构建客户端用户界面。

B/S(Browser/Server)模型

1. 架构概述
  • 浏览器:运行在用户的计算机上,通过Web浏览器访问Web应用程序。浏览器与服务器进行通信,通过HTTP/HTTPS协议进行数据交换。

  • 服务器:运行在服务器端,处理来自浏览器的请求并生成响应。响应通常是HTML、CSS和JavaScript代码。

2. 优点
  • 跨平台:用户只需要一个支持Web的浏览器,不需要安装额外的软件。应用程序可以在不同的操作系统和设备上运行。

  • 易于维护:更新和维护只需要在服务器端进行,用户端不需要进行软件更新。

  • 简化部署:用户通过浏览器访问应用程序,减少了客户端的部署和安装复杂度。

  • 广泛支持:支持各种终端设备,如PC、平板、手机等。

3. 缺点
  • 性能限制:浏览器的性能受限于其处理能力和网络延迟,可能不如本地应用程序高效。

  • 界面限制:Web应用程序的用户界面通常受限于浏览器的功能,可能不如桌面应用程序灵活。

  • 离线功能:虽然现代Web技术如PWA(渐进式Web应用)可以提供有限的离线支持,但传统的Web应用程序通常依赖于持续的网络连接。

4. 应用场景
  • Web应用程序(如在线办公、电子商务网站)

  • 在线服务(如银行服务、社交媒体)

  • 互联网平台(如内容管理系统、论坛)

5. 示例技术
  • Web服务器:如Apache、Nginx,用于处理HTTP请求。

  • Web框架:如Django、Flask、Express,用于开发Web应用程序。

  • 前端技术:如HTML、CSS、JavaScript,用于构建用户界面。

  • API:用于与前端和后端进行通信。

总结

  • C/S模型适用于需要高性能、复杂用户界面的应用,客户端和服务器之间通常通过专用协议进行通信。

  • B/S模型则更适用于需要广泛兼容和简化维护的应用,用户通过浏览器访问服务器上的应用程序。

P2PPeer-to-Peer)模型

是一种网络架构,其中每个节点(或称为对等方)在网络中既是客户端也是服务器。每个节点可以直接与其他节点通信并共享资源,而不依赖于中心服务器。

优点

  • 去中心化:没有单一的故障点,增强了系统的可靠性和鲁棒性。

  • 扩展性:节点数量增加时,系统性能通常会提升,因为每个新节点都可以提供更多资源。

  • 资源共享:节点可以共享存储、计算能力或其他资源。

缺点

  • 安全性:去中心化可能导致安全隐患,如数据泄露和恶意行为。

  • 管理复杂:难以对每个节点进行统一管理和控制。

  • 性能问题:网络性能依赖于每个节点的带宽和处理能力,可能会出现性能瓶颈。

应用场景

  • 文件共享(如BitTorrent)

  • 区块链和加密货币(如比特币)

  • 去中心化应用(DApps)

示例技术

  • BitTorrent协议:用于文件共享,通过P2P网络分发文件。

  • 区块链技术:使用P2P网络维护去中心化的账本

网络编程之TCP

1、模式 C/S 模式 ==》服务器/客户端模型

server:socket()-->bind()--->listen()-->accept()-->recv()-->close()

client:socket()-->connect()-->send()-->close();

int listen(int sockfd, int backlog);

功能:在参数1所在的套接字id上监听等待链接。

参数:

sockfd:套接字描述符,该套接字之前需要使用 socket 函数创建。

backlog:指定系统在处理连接之前,允许排队的最大连接数。

返回值:成功 0

失败 -1;

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数说明

  • sockfd:监听套接字的文件描述符。该套接字应该是已经通过 socket 函数创建,并且已经通过 bindlisten 函数设置为监听状态。

  • addr:指向 sockaddr 结构体的指针,用于存储客户端的地址信息。此参数可以是 NULL,如果不需要获取客户端地址信息的话。

  • addrlen:指向 socklen_t 类型的变量的指针,表示 addr 参数指向的地址结构体的长度。在调用 accept 前,addrlen 应该包含 addr 所指向的结构体的大小(例如 sizeof(struct sockaddr_in))。调用成功后,addrlen 将被设置为实际返回的地址结构体的长度。

返回值

  • 成功:返回一个新的套接字描述符,用于与客户端通信。这个描述符是从监听套接字中接受到的连接的专用套接字。你可以使用这个描述符进行读写操作。

  • 失败:返回 -1,并设置 errno 以指示错误原因。

总结

  • accept 函数用于从监听套接字中接受客户端的连接请求,并返回一个新的套接字描述符用于与客户端进行数据交换。

  • 它是 TCP 连接的核心部分,与 socketbind、和 listen 函数配合使用,构成了 TCP 服务器的基本流程。

  • 使用 accept 后,通常会进行数据的读取和处理,然后关闭套接字以释放资源。

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

在 Linux 系统编程中,recv 函数用于从已连接的套接字中接收数据。这是一个非常重要的函数,广泛应用于网络编程中,特别是在处理 TCP 套接字时。recv 函数从套接字接收数据并将其存储到指定的缓冲区中。

#include <sys/types.h> #include <sys/socket.h>

参数说明

  • sockfd:套接字描述符,指向一个已连接的套接字。该套接字必须已经通过 socket 函数创建,并且通过 connect 函数建立了连接(对于 TCP 套接字)。

  • buf:指向缓冲区的指针,用于存储接收到的数据。

  • len:缓冲区的大小,以字节为单位。这个值表示 recv 函数最多可以读取 len 字节的数据。

  • flags:接收数据的选项。这个参数可以是以下值之一,或其组合:

    • 0:没有特殊标志,函数将会阻塞,直到数据可读。

    • MSG_OOB:接收带外数据。

    • MSG_PEEK:查看数据但不移除它。下一次 recv 调用将会再次返回这些数据。

    • MSG_DONTWAIT:使 recv 函数在非阻塞模式下工作。

返回值

  • 成功:返回接收到的字节数。如果返回值为 0,表示对方关闭了连接(对于 TCP 套接字)。

  • 失败:返回 -1,并设置 errno 以指示错误原因。

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

在 Linux 系统编程中,send 函数用于向已连接的套接字发送数据。它是网络编程中处理数据发送的重要函数,通常用于 TCP 套接字中。

#include <sys/types.h> #include <sys/socket.h>

参数说明

  • sockfd:套接字描述符,指向一个已连接的套接字。必须通过 socket 创建,并通过 connect 连接(对于 TCP 套接字)。

  • buf:指向要发送的数据的指针。

  • len:要发送的数据的字节数。

  • flags:发送数据的选项。常见值包括:

    • 0:使用默认行为,函数可能会阻塞,直到数据被发送。

    • MSG_OOB:发送带外数据。

    • MSG_DONTROUTE:不通过路由发送数据,通常用于测试目的。

    • MSG_NOSIGNAL:阻止在信号处理期间产生 SIGPIPE 信号。

返回值

  • 成功:返回实际发送的字节数。如果发送的字节数小于 len,说明数据可能被分段发送,需要在之后的 send 调用中继续发送剩余数据。

  • 失败:返回 -1,并设置 errno 以指示错误原因。

总结

  • send 函数用于向已连接的套接字发送数据,并通过 buf 指定的缓冲区传输数据。

  • 它支持不同的标志来改变发送行为,例如防止产生 SIGPIPE 信号(MSG_NOSIGNAL)。

  • 处理返回值和错误对于确保数据成功发送和处理异常情况至关重要。

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

int on = 1;

setsockopt(listfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

setsockopt 函数是 Linux 系统编程中用于设置套接字选项的一个重要函数。它允许程序员对套接字进行配置,以便调整其行为和特性。

参数说明

  • sockfd: 套接字描述符,是先前通过 socket 函数创建的套接字。

  • level: 指定选项的级别,通常是协议层次。常见的值包括:

    • SOL_SOCKET: 套接字级别选项

    • IPPROTO_TCP: TCP 协议级别选项

    • IPPROTO_IP: IP 协议级别选项

  • optname: 要设置的选项名称,具体选项根据 level 而不同。例如,SO_RCVBUFSO_KEEPALIVE 等。

  • optval: 指向包含选项值的内存区域的指针。选项值的类型和大小依赖于 optname

  • optlen: optval 所指向的内存区域的大小(以字节为单位)。

SOL_SOCKET 层级:

  • SO_REUSEADDR: 允许重用本地地址。(bind:address already in use)

eg:

Ser

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr* (SA);
int main(int argc, char *argv[])
{
    //监听套接字
    int listfd = socket(AF_INET,SOCK_STREAM,0 );
    if(-1 ==listfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");
    int ret = bind(listfd,(SA)&ser,sizeof(ser));
    if(-1 ==ret)
    {
        perror("bind");
        exit(1);
    }
    //建立连接的排队数
    listen(listfd,3);
    socklen_t len = sizeof(cli);
    //通讯套接字
    int conn = accept(listfd,(SA)&cli,&len);
    if(-1 == conn)
    {
        perror("accept");
        exit(1);
    }
    while(1)
    {   
        char buf[512]={0};
        int rd_ret = recv(conn,buf,sizeof(buf),0);
        if(rd_ret<=0)
        {
            break;
        }
        printf("cli:%s\n",buf);
        time_t tm;
        time(&tm);
        sprintf(buf,"%s %s",buf,ctime(&tm));
        send(conn,buf,strlen(buf),0);
    }
    close(listfd);
    close(conn);
    return 0;
}

Cli

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr* (SA);


int main(int argc, char *argv[])
{

    int conn= socket(AF_INET,SOCK_STREAM,0);
    if(-1 == conn)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");

    int ret = connect(conn,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("connect");
        exit(1);
    }
    while(1)
    {
        char buf[512]="hello,this tcp test";
        send(conn,buf,strlen(buf),0);
        bzero(buf,sizeof(buf));
        recv(conn,buf,sizeof(buf),0);
        printf("ser:%s\n",buf);
        sleep(1);
    }
    close(conn);
    return 0;
}

三次握手,四次挥手

三次握手(TCP连接建立)

  1. 第一次握手:客户端发送SYN

    1. 客户端向服务器发送一个SYN(同步)包,以初始化一个连接请求。这个包的SYN标志位被设置为1,并且客户端会选择一个初始的序列号(SEQ)。

  2. 第二次握手:服务器回应SYN-ACK

    1. 服务器收到客户端的SYN包后,确认客户端的请求,向客户端发送一个SYN-ACK包。这个包中SYN和ACK标志位都被设置为1。服务器也会选择一个自己的序列号,并确认客户端的序列号。

  3. 第三次握手:客户端确认ACK

    1. 客户端收到服务器的SYN-ACK包后,发送一个ACK(确认)包给服务器。此包中ACK标志位被设置为1,并确认服务器的序列号。到此为止,客户端和服务器之间的连接就建立起来了。

四次挥手(TCP连接断开)

  1. 第一次挥手:主动关闭方发送FIN

    1. 主动关闭连接的一方(通常是客户端)发送一个FIN(终止)包给对方,表示数据已经发送完毕,希望关闭连接。此时客户端进入FIN_WAIT_1状态。

  2. 第二次挥手:被动关闭方回应FIN-ACK

    1. 被动关闭方(通常是服务器)收到FIN包后,发送一个FIN-ACK包来确认收到终止请求,并表示自己也准备关闭连接。此时服务器进入CLOSE_WAIT状态。

  3. 第三次挥手:主动关闭方接收ACK

    1. 主动关闭方收到服务器的FIN-ACK包后,发送一个ACK包确认收到了关闭请求。此时客户端进入FIN_WAIT_2状态。

  4. 第四次挥手:被动关闭方关闭连接

    1. 被动关闭方在发送FIN-ACK包后,完成了数据的传输和关闭连接的准备。此时,服务器会发送一个ACK包来确认连接已关闭,然后进入LAST_ACK状态,直到确认ACK包被收到后才彻底关闭连接。

hw:tcp_cp

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <fcntl.h>
typedef struct sockaddr* (SA);
int main(int argc, char *argv[])
{
    //监听套接字
    int listfd = socket(AF_INET,SOCK_STREAM,0 );
    if(-1 ==listfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");
    int on = 1;// bind: Address already in use   异常断开,四次挥手顺序不对情况
    setsockopt(listfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    int ret = bind(listfd,(SA)&ser,sizeof(ser));
    if(-1 ==ret)
    {
        perror("bind");
        exit(1);
    }
    //建立连接的排队数
    listen(listfd,3);
    socklen_t len = sizeof(cli);
    //通讯套接字
    int conn = accept(listfd,(SA)&cli,&len);
    if(-1 == conn)
    {
        perror("accept");
        exit(1);
    }
    int fd = open("1.png",O_WRONLY|O_CREAT|O_TRUNC,0666);
    if(-1 == fd)
    {
        perror("open");
        exit(1);
    }
    while(1)
    {   
        char buf[4096]={0};
        int rd_ret = recv(conn,buf,sizeof(buf),0);
        if(rd_ret<=0)
        {
            break;
        }
        write(fd,buf,rd_ret);
        strcpy(buf,"go on");
        send(conn,buf,strlen(buf),0);
    }
    close(listfd);
    close(conn);
    close(fd);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <fcntl.h>
typedef struct sockaddr* (SA);


int main(int argc, char *argv[])
{

    int conn= socket(AF_INET,SOCK_STREAM,0);
    if(-1 == conn)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");

    int ret = connect(conn,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("connect");
        exit(1);
    }
    int fd = open("/home/linux/1.png",O_RDONLY);
    if(-1 ==fd)
    {
        perror("open");
        exit(1);
    }
    while(1)
    {
        char buf[4096]={0};
        int rd_ret = read(fd,buf,sizeof(buf));
        if(rd_ret<=0)
        {
            break;
        }
        send(conn,buf,rd_ret,0);
        bzero(buf,sizeof(buf));
        recv(conn,buf,sizeof(buf),0);
    }
    close(conn);
    close(fd);
    return 0;
}

hw:tcp_chat

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <signal.h>
typedef struct sockaddr* (SA);
int main(int argc, char *argv[])
{
    //监听套接字
    int listfd = socket(AF_INET,SOCK_STREAM,0 );
    if(-1 ==listfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");

    int on = 1;
    setsockopt(listfd, SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
    int ret = bind(listfd,(SA)&ser,sizeof(ser));
    if(-1 ==ret)
    {
        perror("bind");
        exit(1);
    }
    //建立连接的排队数
    listen(listfd,3);
    socklen_t len = sizeof(cli);
    //通讯套接字
    int conn = accept(listfd,(SA)&cli,&len);
    if(-1 == conn)
    {
        perror("accept");
        exit(1);
    }
    pid_t pid = fork();
    if(pid>0)
    {
        while(1)
        {
            char buf[128]={0};
            printf("to cli:");
            fgets(buf,sizeof(buf),stdin);
            int se_ret = send(conn,buf,strlen(buf),0);
            if(0 == strcmp("#quit\n",buf)
               ||se_ret<0)
            {
                kill(pid,2);
                exit(0);
            }
        }
    }
    else if(0 == pid)
    {
        while(1)
        {
            char buf[128]={0};
            int rd_ret = recv(conn,buf,sizeof(buf),0);
            if(0 == strcmp(buf,"#quit\n")
               || rd_ret<=0)
            {
                kill(getppid(),2);
                exit(0);
            }
            printf("cli:%s",buf);
            fflush(stdout);
        }
    }
    
    else 
    {
        perror("fork");
        exit(1);
               
    }
    close(listfd);
    close(conn);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <pthread.h>
typedef struct sockaddr* (SA);

void* th1(void* arg)
{
    int sockfd = *(int*)arg;
    while(1)
    {
    
        char buf[128]={0};
        printf("to ser:");
        fgets(buf,sizeof(buf),stdin);
        int se_ret = send(sockfd,buf,strlen(buf),0);
        if(0==strcmp(buf,"#quit\n")
           || se_ret<0)
        {
            exit(0);
        }
    }
    return NULL;
}
void* th2(void* arg)
{
    int sockfd = *(int*)arg;
    while(1)
    {
    
        char buf[128]={0};
        int rd_ret = recv(sockfd,buf,sizeof(buf),0);
        if(0 == strcmp(buf,"#quit\n") 
           ||rd_ret<=0)
        {
            exit(0);
        }
        printf("ser:%s",buf);
        fflush(stdout);
    }
    return NULL;
}
int main(int argc, char *argv[])
{

    int conn= socket(AF_INET,SOCK_STREAM,0);
    if(-1 == conn)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr =inet_addr("127.0.0.1");

    int ret = connect(conn,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("connect");
        exit(1);
    
    }
    pthread_t tid1,tid2;
    pthread_create(&tid1,NULL,th1,&conn);
    pthread_create(&tid2,NULL,th2,&conn);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);

    close(conn);
    return 0;
}

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

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

相关文章

C语言 | Leetcode C语言题解之第384题打乱数组

题目&#xff1a; 题解&#xff1a; typedef struct {int* num;int* src;int numsize; } Solution;Solution *obj NULL;Solution* solutionCreate(int* nums, int numsSize) {if (obj ! NULL) {return obj;}Solution *obj (Solution*)malloc(sizeof(Solution));obj->nums…

#C++ 笔记二

四、运算符重载 1.友元 1.1 概念 类实现了数据的隐藏和封装&#xff0c;类的数据成员一般定义为私有成员&#xff0c;仅能通过类的公有成员函数才能进行读写。 如果数据成员定义成公共的&#xff0c;则又破坏了封装性。但是在某些情况下&#xff0c;需要频繁的读写数据成员…

Java 7.3 - 分布式 id

分布式 ID 介绍 什么是 ID&#xff1f; ID 就是 数据的唯一标识。 什么是分布式 ID&#xff1f; 分布式 ID 是 分布式系统中的 ID&#xff0c;它不存在于现实生活&#xff0c;只存在于分布式系统中。 分库分表&#xff1a; 一个项目&#xff0c;在上线初期使用的是单机 My…

2-80 基于matlab-GUI,实现kalman滤波对目标物的位置进行检测跟踪

基于matlab-GUI,实现kalman滤波对目标物的位置进行检测跟踪。检测汽车中心和最大半径&#xff0c;与背景差分选择较大差异的区域进行形态学处理&#xff0c;用冒泡法对目标面积从大到小排序。程序已调通&#xff0c;可直接运行。 2-80 kalman视频跟踪滤波 - 小红书 (xiaohongsh…

光学涡旋Talbot阵列照明器的matlab模拟与仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 光学涡旋 Talbot 阵列照明器是一种利用光学涡旋&#xff08;Optical Vortex&#xff09;和 Talbot 效应&#xff08;Talbot Effect&#xff09;相结合的技术&…

【HTML源码】上传即可使用的在线叫号系统源码

这个叫号系统的过程是这样的 接了一个任务&#xff0c;某学校要对学生进行逐个面试&#xff0c;希望能有类似医院门诊那种叫号系统。 条件&#xff1a;首先说硬件&#xff0c;就是教室里边一台笔记本电脑&#xff0c;同屏到教室外面的电视机。 需求&#xff1a;软件需求是可…

汉诺塔递归解决思路图解分析,python代码实现

目录 4.假设四层汉诺塔&#xff0c;n4&#xff0c;利用整体思想分解为两层的情况 3.分解到n3 3.1 分解上面n4时第一个步骤&#xff1a; 3.2 分解上面n4时第三个步骤&#xff1a; 2.继续分解到n2 &#xff08;同理略&#xff09; 1.当分解到n1 python代码 问题&#xff1…

【Linux】升级OpenSSH版本规避远程代码执行漏洞

本文首发于 ❄️慕雪的寒舍 升级OpenSSH版本规避远程代码执行漏洞。 说明 今天早上逛别人的博客的时候看到了这个重磅消息。OpenSSH爆出能远程通过root身份执行任意代码的漏洞&#xff0c;影响版本是 8.5p1 < OpenSSH < 9.8p1&#xff0c;奇安信的报告可以点我查看。 上…

计算机三级网络第4套练习记背

计算机三级网络第4套练习记背

全志/RK安卓屏一体机:医疗自助服务终端,支持鸿蒙国产化

医疗自助服务终端 为了解决传统医疗模式下的“看病难、看病慢”等问题&#xff0c;提高医疗品质、效率与效益&#xff0c;自助服务业务的推广成为智慧医疗领域实现信息化建设、高效运作的重要环节。 医疗自助服务终端是智慧医疗应用场景中最常见的智能设备之一&#xff0c;它通…

Linux学习笔记(4)----Debian压力测试方法

使用命令行终端压力测试需要两个实用工具&#xff1a;s-tui和stress sudo apt install s-tui stress 安装完成后&#xff0c;在终端中启动 s-tui实用工具&#xff1a; s-tui 执行后如下图&#xff1a; 你可以使用鼠标或键盘箭头键浏览菜单&#xff0c;然后点击“压力选项(Str…

day44.动态规划

718.最长重复子数组 给两个整数数组 nums1 和 nums2 &#xff0c;返回 两个数组中 公共的 、长度最长的子数组的长度 。 思路:1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义: dp[i][j] &#xff1a;以下标i - 1为结尾的A&#xff0c;和以下标j - 1为结尾的B&…

【论文速读】|RO-SVD:一种用于 AIGC 应用的可重构硬件版权保护框架

本次分享论文&#xff1a;RO-SVD: A Reconfigurable Hardware Copyright Protection Framework for AIGC Applications 基本信息 原文作者&#xff1a;Zhuoheng Ran, Muhammad A.A. Abdelgawad, Zekai Zhang, Ray C.C. Cheung, Hong Yan 作者单位&#xff1a;香港城市大学电…

linux 内核代码学习(七)

linux内核代码的研究中断了一段时间了&#xff0c;现在又重新开始了研究&#xff0c;个人觉得linux内核的学习是没有上限的&#xff0c;总是一个温故而知新的过程&#xff0c;是一个不断积累的过程。首先还是要先搭建一个方便自己学习和研究的平台&#xff0c;经过不断的尝试&a…

Java的IO模型详解-BIO,NIO,AIO

一、BIO相关知识 Java 的 BIO (Blocking I/O) 模型是基于传统的同步阻塞 I/O 操作。在这种模型中&#xff0c;每个客户端连接都需要一个独立的线程来处理请求。当线程正在执行 I/O 操作时&#xff08;如读取或写入&#xff09;&#xff0c;它会被阻塞&#xff0c;直到操作完成…

三级_网络技术_55_应用题

一、 请根据下图所示网络结构回答下列问题。 1.填写RG的路由表项。 目的网络/掩码长度输出端口__________S0&#xff08;直接连接&#xff09;__________S1&#xff08;直接连接&#xff09;__________S0__________S1__________S0__________S1 (2)在不改变路由表项的前提下&…

django学习入门系列之第十点《案例 用户登录》

文章目录 案例 用户登录安全认证django中的隐藏值获得用户账户密码空值 往期回顾 案例 用户登录 安全认证 ​ 如果提交数据后&#xff0c;发现并没有跳转到自己想要的界面&#xff0c;是因为django比Flask多一层 ”安全机制“ 的东西 解决方法&#xff1a; {% csrf_token %…

使用maven搭建微服务框架

徒手搭建cloud 1.认准SpringBoot,SpringCloud,SpringCloudAlibaba版本之间的对用关系 官网给出了声明&#xff1a;https://github.com/alibaba/spring-cloud-alibaba/wiki 2.选择好版本之后 spring bootspring cloudspring cloud alibaba2.3.12.RELEASEHoxton.SR102.2.5.REL…

Ps:工具预设面板

Ps菜单&#xff1a;窗口/工具预设 Window/Tool Presets 工具预设 Tool Presets面板可以为 Photoshop 的图像编辑工作带来极大的便利。 定义好相关的工具预设后&#xff0c;可以直接调用&#xff0c;而不管现在处于什么工具或什么样的参数状态&#xff0c;省去了再次设置参数的麻…

使用 树莓派3B+ 对日本葡萄园进行经济实惠的环境监测

对于 菊岛邦夫—Vineyard Kikushima 而言&#xff0c;Raspberry Pi 生态系统提供了支持和信息&#xff0c;通过基于温度和湿度监测的有针对性的最低限度杀虫剂方案&#xff0c;来提高葡萄的健康产量。 Vineyard Kikushima&#xff1a;http://vykikushima.greater.jp/vineyards…