Linux- 网络编程初探

news2024/12/23 3:06:34

原始套接字(Raw Socket)

原始套接字(Raw Socket)是一种提供较低级别网络访问的套接字。通过使用原始套接字,应用程序可以直接发送或接收网络层如IP的数据包,或者传输层如TCP、UDP的段,而无需通过常规的套接字API提供的协议处理。

以下是原始套接字的一些关键点:

  1. 协议独立性:使用原始套接字,我们可以操作或构建自己的协议,或者直接与现有协议(如ICMP)交互。

  2. 绕过内核处理:通常,当发送或接收数据包时,操作系统内核会为我们处理很多细节,例如TCP的三次握手或IP头的填充。但是,使用原始套接字,我们可以直接构建或解析这些协议,从而绕过标准的内核处理。

  3. 特权:由于原始套接字提供了对网络的低级访问,使用它们通常需要特权,例如root权限。

  4. 应用场景

    • 网络诊断和测试工具:例如,ping使用原始套接字发送和接收ICMP回显请求和回显响应。
    • 定制协议的实现:例如,如果我们想实验一个新的传输层协议。
    • 安全研究和网络攻击:例如,执行某些类型的DoS攻击或网络扫描。
  5. 创建原始套接字:在Linux中,我们可以使用socket函数并为其提供AF_INET(对于IPv4)或AF_INET6(对于IPv6)以及SOCK_RAW来创建一个原始套接字。

  6. 手动头部处理:使用原始套接字,需要手动构建或解析协议头部。例如,如果我们正在发送一个TCP段,我们需要手动构建IP和TCP头部,并设置所有必要的字段。同样,当从一个原始套接字接收数据时,我们将获取整个数据包,需要自己解析它。

  7. 混杂模式:如果我们想使用原始套接字捕获一个接口上的所有流量(而不仅仅是发给特定地址的流量),我们需要将接口设置为混杂模式。

需要注意的是,虽然原始套接字提供了强大的功能,但也需要小心使用。手动处理协议细节容易导致错误,并可能引起网络问题或安全隐患。

Socket()

socket()函数是计算机网络编程中的核心函数之一,用于创建一个新的套接字。套接字是端到端的通信链路,是进程之间进行网络通信的主要手段。

下面详细介绍socket()函数:

函数原型

int socket(int domain, int type, int protocol);

参数

  1. domain(或称为family):指定使用哪种地址族。常见的选择包括:

    • AF_INET:IPv4 地址族。用于IPv4网络通信。
    • AF_INET6:IPv6 地址族。用于IPv6网络通信。
    • AF_UNIX:本地套接字(UNIX 域套接字)地址族。用于同一机器上的进程间通信。
  2. type:指定套接字的类型。常见的选择包括:

    • SOCK_STREAM:提供面向连接、可靠、双向的字节流服务。典型的协议有TCP。
    • SOCK_DGRAM:提供无连接的、不可靠的数据报服务。典型的协议有UDP。
    • SOCK_RAW:提供原始套接字访问,允许直接发送或接收协议如IP的数据包。
    • SOCK_SEQPACKET:提供面向连接的、可靠的、固定最大长度的记录序列。
  3. protocol:指定要使用的协议。通常,当给定了套接字的类型时,可以将此参数设置为0,让系统自动选择合适的协议。例如,当typeSOCK_STREAM时,系统通常选择TCP作为协议。

返回值

  • 成功:返回一个非负描述符,代表新创建的套接字。
  • 失败:返回-1,并设置相应的错误码。

使用示例

创建一个用于IPv4 TCP通信的套接字:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
    perror("socket creation failed");
    exit(EXIT_FAILURE);
}

创建一个用于IPv4 UDP通信的套接字:

int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
    perror("socket creation failed");
    exit(EXIT_FAILURE);
}

注意事项

  1. 创建套接字只是第一步。为了实际上进行通信,还需要其他函数,如bind(), listen(), accept(), connect(), send(), 和 recv(),来配置并操作这个套接字。
  2. 对于TCP服务端,通常在socket()之后会调用bind(), listen()accept()来绑定地址、监听连接和接受连接。
  3. 对于TCP客户端,通常在socket()之后会调用connect()来连接到服务器。
  4. 对于UDP,没有建立或接受连接的概念,所以只需创建套接字,然后可以直接使用sendto()recvfrom()进行通信。

socket()函数是网络编程中的基础,几乎所有的网络应用程序都会在某个地方使用它来开始其网络通信。

bind()

bind() 是套接字编程中的一个关键函数,用于将套接字与特定的IP地址和端口号绑定。它通常在服务器设置期间使用,以指定服务器将在哪个地址和端口监听即将到来的客户端连接。

函数原型:

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

参数:

  1. sockfd: 这是一个套接字描述符,它表示要绑定的套接字。

  2. addr: 这是一个指向struct sockaddr的指针,该结构定义了套接字的地址(IP和端口)。在实践中,通常使用特定于协议的结构(如struct sockaddr_in对于IPv4)来填充这个参数,并将其指针类型强制转换为struct sockaddr *

  3. addrlen: 这是地址结构的大小(例如,对于IPv4,这将是sizeof(struct sockaddr_in))。

返回值:

  • 成功时,bind() 返回0。
  • 失败时,返回-1,并设置errno以指示错误的原因。

常见的使用模式:

在服务器中,通常首先创建一个套接字,然后使用bind()将它绑定到一个地址和端口。以下是一个简化的示例,演示如何使用bind()为IPv4地址绑定套接字:

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

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // Create a TCP socket
    if (sockfd < 0) {
        perror("Error creating socket");
        return 1;
    }

    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;            // Address family for IPv4
    server_addr.sin_addr.s_addr = INADDR_ANY;    // Listen on any interface
    server_addr.sin_port = htons(8080);          // Listen on port 8080

    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Error binding socket");
        return 1;
    }

    // ... the server can then proceed to listen and accept connections

    return 0;
}

常见错误和注意事项:

  1. Address already in use: 如果尝试绑定到已被另一个套接字使用的地址和端口,将会出现此错误。这通常发生在服务器崩溃并尝试重新启动,但由于之前的套接字仍处于“TIME_WAIT”状态,所以它不能立即绑定。使用setsockopt()SO_REUSEADDR可以帮助解决此问题。

  2. Permission denied: 通常,只有root用户才能绑定到低于1024的端口。

  3. 确保在绑定套接字之前填充了整个sockaddr_in结构,并正确设置了sin_familysin_addr.s_addrsin_port字段。

  4. 使用htons()函数确保端口号是网络字节顺序。

通过合理地使用bind()函数,开发人员可以确保他们的服务器监听特定的IP地址和端口,从而等待客户端的连接。

listen()

listen() 是套接字API中的一个函数,用于让一个套接字进入监听模式,从而能够接收来自客户端的连接请求。这是创建服务器应用程序的必要步骤之一。

函数原型:

int listen(int sockfd, int backlog);

参数:

  1. sockfd: 一个套接字描述符,它应该先前已经使用 socket() 创建并使用 bind() 绑定到一个特定的地址和端口。

  2. backlog: 这个参数定义了等待队列的大小,也就是说,系统应该允许等待处理(未accept()的)的连接数量。当有更多的客户端尝试连接,超过了backlog指定的数量时,系统会开始拒绝这些新的连接请求。

返回值:

  • 如果函数调用成功,则返回0。
  • 如果出现错误,则返回-1,并设置errno以指示出现的特定错误。

使用:

一旦使用bind()函数将套接字绑定到一个地址和端口后,我们可以调用listen()以进入监听模式。在此模式下,套接字准备接受来自客户端的连接请求。

这是一个简单的示例:

int sockfd = socket(AF_INET, SOCK_STREAM, 0);  // Create a socket

// ... (bind the socket to an address using bind() here)

if (listen(sockfd, 5) < 0) {  // Allow up to 5 pending connections
    perror("Error while trying to listen");
    return 1;
}

此示例创建了一个套接字,并设置其最大待处理连接数为5。当超过5个客户端连接并等待被accept()时,任何进一步的连接请求都将被拒绝,直到有一个连接被accept()为止。

注意:

  • 在调用 listen() 之前,必须先调用 bind()
  • backlog 参数的具体含义和行为可能因操作系统而异。在某些系统上,它表示待处理的连接数量,而在其他系统上,它可能包括已被accept()但尚未由应用程序处理的连接。
  • backlog 队列已满,进一步的连接请求可能会被拒绝。因此,为了避免这种情况,服务器应该尽快处理连接。
  • 通常,在 listen() 之后,会进入一个循环,不断地调用 accept() 来接受并处理来自客户端的连接。

总之,listen() 函数是服务器套接字编程中的关键步骤,使得服务器能够开始接受客户端的连接请求。

accept()

accept() 是套接字编程中的一个关键函数,用于从已经处于监听模式的套接字中提取连接请求,并返回一个新的套接字描述符,该描述符代表与客户端之间的新连接。此函数在服务器应用程序中经常使用,以处理来自客户端的连接请求。

函数原型:

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

参数:

  1. sockfd: 这是一个处于监听模式的套接字描述符,通常先前已经通过 socket() 创建并通过 bind()listen() 函数配置。

  2. addr: 这是一个指向struct sockaddr的指针,当 accept() 调用返回时,这个结构将被填充与已经接受的连接的远程端(客户端)的地址信息。

  3. addrlen: 这是一个值-结果参数。在调用 accept() 之前,它应该被设置为addr指向的地址结构的大小。当函数返回时,addrlen 将被设置为实际的地址大小。

返回值:

  • 成功时,accept() 返回一个新的套接字描述符,代表与客户端的新连接。此新描述符应用于后续的所有通信(例如 send()recv() 调用)。

  • 失败时,返回 -1,并设置 errno 以指示出现的错误。

使用和注意事项:

  1. 在服务器应用程序中,通常在 listen() 函数调用后立即调用 accept(),等待客户端的连接。

  2. accept() 函数是阻塞的,这意味着它将等待,直到一个连接请求可用,除非套接字已被配置为非阻塞。

  3. 返回的新套接字描述符与原始的监听套接字是独立的。应使用新的套接字描述符进行与客户端的所有通信,并继续使用原始的监听套接字来接受其他连接请求。

  4. 通常,服务器将为每个接受的连接启动一个新的线程或进程以并行处理多个连接。

  5. addraddrlen 参数是可选的;如果我们不关心客户端的地址,我们可以设置这两个参数为 NULL。

示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len = sizeof(client_addr);

    // Assuming server_sock has been created and set up for listening...

    client_sock = accept(server_sock, (struct sockaddr *) &client_addr, &client_addr_len);
    if (client_sock < 0) {
        perror("Error on accept");
        return 1;
    }

    // Use client_sock for communication with the client...

    close(client_sock);
    return 0;
}

这个简单的例子展示了如何使用 accept() 函数从 server_sock 监听套接字中接受一个新的连接,并使用 client_sock 与客户端进行通信。

connect()

connect() 是套接字编程中的一个函数,主要用于客户端应用程序。该函数使客户端尝试与服务器端的指定地址建立连接。

函数原型:

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

参数:

  1. sockfd: 这是我们想要与远程主机连接的套接字的描述符。

  2. addr: 这是一个指向struct sockaddr的指针,包含我们想要连接的远程主机的地址信息。在实际应用中,通常使用特定于协议的结构(如struct sockaddr_in对于IPv4)并将其类型强制转换为struct sockaddr *

  3. addrlen: 这是地址结构的大小,例如对于IPv4地址,这通常是sizeof(struct sockaddr_in)

返回值:

  • 成功时,connect() 返回0。

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

使用和注意事项:

  1. 在客户端应用程序中,我们通常首先使用 socket() 函数创建一个套接字,然后使用 connect() 函数尝试与服务器连接。

  2. 如果 connect() 成功,客户端可以开始使用 send()recv() 或其他相关函数与服务器通信。

  3. 如果连接尝试失败,connect() 将返回-1。这可能是由于多种原因,例如服务器未在指定的地址和端口上运行,网络故障,或服务器拒绝连接。

  4. connect() 在默认情况下是阻塞的,这意味着它会等待,直到连接成功或发生错误。但是,我们可以将套接字设置为非阻塞模式,使 connect() 立即返回,并后续使用 select()poll() 来等待连接完成。

示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() {
    int client_sock;
    struct sockaddr_in server_addr;

    // Assuming client_sock has been created...

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080); // server port
    inet_pton(AF_INET, "192.168.1.1", &server_addr.sin_addr); // server IP

    if (connect(client_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
        perror("Error on connect");
        return 1;
    }

    // Now client_sock is connected and can be used to send or receive data...

    return 0;
}

这个简单的例子展示了如何使用 connect() 函数尝试与运行在192.168.1.1的服务器上的服务连接,该服务监听端口8080

send()

send() 是套接字编程中的一个函数,用于向一个已连接的套接字发送数据。它通常用于TCP套接字,但也可以与其他类型的套接字一起使用。

函数原型:

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

参数:

  1. sockfd: 这是一个已连接的套接字的描述符。

  2. buf: 这是一个指针,指向我们想要发送的数据的缓冲区。

  3. len: 这是buf中我们想要发送的数据的字节数。

  4. flags: 这是一个修改函数操作的标志集合。常见的标志包括 MSG_OOB (用于发送"out-of-band"数据) 和 MSG_NOSIGNAL (阻止在连接断开时发送SIGPIPE信号)。大多数情况下,我们可以简单地将此参数设置为0。

返回值:

  • 成功时,send() 返回实际发送的字节数。请注意,这可能少于我们请求发送的数量。

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

使用和注意事项:

  1. 在一个已连接的TCP套接字上使用send()之前,必须先成功地调用connect()(对于客户端)或accept()(对于服务器)。

  2. TCP是一个流协议,这意味着没有消息边界。连续的send()调用可能会在接收方看起来像一个连续的数据流,而不是单独的消息。

  3. 如果套接字是阻塞的(默认情况),send()可能会阻塞,直到有足够的网络缓冲区可用以发送数据。如果套接字是非阻塞的,而网络缓冲区不可用,则send()将立即返回-1,并将errno设置为EAGAINEWOULDBLOCK

  4. 在连接断开的套接字上调用send()将导致发送一个SIGPIPE信号,除非设置了MSG_NOSIGNAL标志。此信号的默认行为是终止进程,但可以捕获或忽略它。

示例:

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

int main() {
    int sockfd;  // assuming it's already connected
    const char *message = "Hello, server!";
    ssize_t bytes_sent;

    bytes_sent = send(sockfd, message, strlen(message), 0);
    if (bytes_sent < 0) {
        perror("Error on send");
        return 1;
    }

    printf("Sent %zd bytes to server.\n", bytes_sent);
    return 0;
}

这个简单的示例展示了如何使用send()函数将一条消息发送到一个已连接的服务器。

recv()

recv() 函数用于从已连接的套接字接收数据。它主要用于 TCP 套接字,但也可以与其他类型的套接字一起使用。

函数原型:

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

参数:

  1. sockfd: 这是一个已连接的套接字的描述符。

  2. buf: 这是一个指针,指向一个缓冲区,用于存储接收到的数据。

  3. len: 这是缓冲区的大小,即我们期望接收的最大字节数。

  4. flags: 这是一个修改函数操作的标志集合。一些常见的标志包括:

    • MSG_PEEK: 查看即将到来的数据,但不从队列中删除它。
    • MSG_WAITALL: 尝试接收指定的len字节。与默认行为不同,该标志会使函数等待,直到请求的字节数量可用或发生某些错误。
    • MSG_OOB: 用于接收 “out-of-band” 数据。

    在大多数常规操作中,我们可以简单地将此参数设置为0。

返回值:

  • 成功时,recv() 返回实际接收到的字节数。如果连接已关闭,返回0。

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

使用和注意事项:

  1. 在一个已连接的 TCP 套接字上使用 recv() 之前,我们需要先成功调用 connect()(对于客户端)或 accept()(对于服务器)。

  2. TCP 是一个流协议,这意味着没有消息边界。连续的 recv() 调用可能会接收到之前调用的数据的剩余部分。

  3. 如果套接字是阻塞的(默认情况),并且没有数据可用,recv() 会阻塞,直到数据可用。如果套接字是非阻塞的,并且没有数据可用,recv() 会立即返回-1,并将 errno 设置为 EAGAINEWOULDBLOCK

  4. 当连接断开或关闭时,recv() 将返回0。因此,接收到0字节通常意味着对端关闭了连接。

示例:

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

int main() {
    int sockfd;  // assuming it's already connected
    char buffer[1024];
    ssize_t bytes_received;

    bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
    if (bytes_received < 0) {
        perror("Error on recv");
        return 1;
    } else if (bytes_received == 0) {
        printf("The peer has closed the connection.\n");
        return 0;
    }

    buffer[bytes_received] = '\0';  // Null-terminate the string
    printf("Received: %s\n", buffer);
    return 0;
}

这个简单的示例展示了如何使用 recv() 函数从已连接的服务器接收消息,并将其打印出来。

综合案例

下面是一个简单的TCP套接字编程的例子,其中包括一个服务器和一个客户端。服务器接收来自客户端的消息,然后返回相同的消息。

服务器端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

#define SERVER_PORT 8080
#define BUFFER_SIZE 1024

int main() {
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    char buffer[BUFFER_SIZE];
    int bytes_read;

    // 创建套接字
    server_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock == -1) {
        perror("Socket creation failed");
        exit(1);
    }

    // 设置服务器地址结构
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    // 绑定套接字
    if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
        perror("Bind failed");
        exit(1);
    }

    // 监听连接请求
    listen(server_sock, 5);

    printf("Server is listening on port %d...\n", SERVER_PORT);

    socklen_t client_addr_len = sizeof(client_addr);
    client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_addr_len);

    if (client_sock == -1) {
        perror("Accept failed");
        exit(1);
    }

    // 读取和响应客户端的消息
    bytes_read = recv(client_sock, buffer, BUFFER_SIZE, 0);
    buffer[bytes_read] = '\0';
    printf("Received from client: %s\n", buffer);

    send(client_sock, buffer, bytes_read, 0);

    close(client_sock);
    close(server_sock);

    return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define SERVER_PORT 8080
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024

int main() {
    int client_sock;
    struct sockaddr_in server_addr;
    char buffer[BUFFER_SIZE];

    // 创建套接字
    client_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (client_sock == -1) {
        perror("Socket creation failed");
        exit(1);
    }

    // 设置服务器地址结构
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr);

    // 连接到服务器
    if (connect(client_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
        perror("Connect failed");
        exit(1);
    }

    strcpy(buffer, "Hello, Server!");
    send(client_sock, buffer, strlen(buffer), 0);

    int bytes_received = recv(client_sock, buffer, BUFFER_SIZE, 0);
    buffer[bytes_received] = '\0';
    printf("Received from server: %s\n", buffer);

    close(client_sock);

    return 0;
}

运行结果如下:
在这里插入图片描述
上述示例中,服务器创建一个套接字,绑定到本地地址并监听连接。当客户端连接时,服务器接收来自客户端的消息,并将相同的消息发送回客户端。客户端则发送一个简单的消息,并从服务器接收响应。

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

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

相关文章

hive数据库操作,hive函数,FineBI可视化操作

1、数据库操作 1.1、创建数据库 create database if not exists myhive;use myhive;1.2、查看数据库详细信息 desc database myhive;数据库本质上就是在HDFS之上的文件夹。 默认数据库的存放路径是HDFS的&#xff1a;/user/hive/warehouse内 1.3、创建数据库并指定hdfs存…

PASCAL数据集说明

文章目录 一.PASCAL数据集简介1.图像分割 一.PASCAL数据集简介 Pascal VOC2012数据集主要是针对视觉任务中监督学习提供标签数据&#xff0c;它有四个大类别&#xff0c;可以细分为二十个小类别&#xff1a; Person&#xff1a;personAnimal&#xff1a;bird, cat, cow, dog,…

【软件设计师-中级——刷题记录4(纯干货)】

目录 进度管理工具Grantt图&#xff1a;程序语言基础&#xff1a;高级语言源程序模式&#xff1a; 每日一言&#xff1a;持续更新中... 个人昵称&#xff1a;lxw-pro 个人主页&#xff1a;欢迎关注 我的主页 个人感悟&#xff1a; “失败乃成功之母”&#xff0c;这是不变的道理…

统计的基本概念及抽样分布

文章目录 &#x1f34b;引言&#x1f34b;总体&#xff08;Population&#xff09;&#x1f34b;总体参数 &#x1f34b;样本&#xff08;Sample&#xff09;&#x1f34b;随机样本&#x1f34b;样本统计量 &#x1f34b;统计量&#xff08;Statistic&#xff09;&#x1f34b;…

印度市场最全开发攻略,收藏一篇就够了

一提到印度市场&#xff0c;很多外贸人都会感到望而却步&#xff0c;他们说做一个印度客户&#xff0c;就等于经历了人生的酸甜苦辣…… 然而&#xff0c;印度市场也是全球一块潜力无穷的大蛋糕&#xff0c;这体现在其庞大的人口和雄厚的银行资金上&#xff08;这也是市场容量…

想学python找不到合适的书籍?它来了!入门python只需要这一本书就够了!

想学python找不到合适的书籍&#xff1f;看了视频还是不知如何下手&#xff1f; 《python王者归来》 它来了&#xff01;由清华大学出版社出版&#xff01;入门python只需要这一本书就够了&#xff01; 【PDF版领取见文末】 这是一本python入门书。无论你是计算机专业的大学生…

愿你放飞梦想,国庆快乐!Wish you a happy National Day!

国庆节是一个国家为纪念自己而设立的法定节日。它们通常是国家独立 、宪法签署、国家元首诞生或其他重要纪念日&#xff0c;有些是国家守护神的圣日。National Day is a legal holiday made by a country to commemorate the country itself. They are usually the independenc…

vue3 + elementPlus实现select下拉框插入确定和取消按钮。

实现思路 Select 选择器 | Element Plus 1、select方法visible-change这个方法是下拉框出现/隐藏时触发&#xff0c;当显示的时候将两个按钮插入到下拉框里面&#xff0c;是基于原生插入DOM的这种方式&#xff1b; 2、通过vue3 ref获取selectDOM&#xff0c;在获取select的p…

Konva基本处理流程和相关架构设计

前言 canvas是使用JavaScript基于上下文对象进行2D图形的绘制的HTML元素&#xff0c;通常用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。基于Canvas之上&#xff0c;诞生了例如 PIXI、ZRender、Fabric、Konva等 Canvas渲染引擎&#xff0c;兼顾易用的同时…

Java项目实战-查询用户列表接口服务搭建

概述 这里通过设计一个对用户进行增删改查的接口服务&#xff0c;来练习java项目工程化、Spring框架、Mybatis框架的实际应用 本项目目录 上一节初始化项目&#xff0c;已经controller层了&#xff0c;下方新建包&#xff1a;pojo、mapper、service pojo:所有的实体类都放这…

ternsor合并与分割

拼接&#xff1a;拆分&#xff1a;Cat、StackSplit、Chunk 1、cat&#xff08;concat&#xff09; 统计班级学生成绩&#xff1a; [class1-4, students, scores] [class5-9, students, scores] 将这九名学生的成绩进行合并 a torch.rand(4, 32, 8) b torch.rand(5, 32, 8…

A股风格因子看板 (2023.09 第09期)

该因子看板跟踪A股风格因子&#xff0c;该因子主要解释沪深两市的市场收益、刻画市场风格趋势的系列风格因子&#xff0c;用以分析市场风格切换、组合风格景露等。 今日为该因子跟踪第9期&#xff0c;指数组合数据截止日2023-08-31&#xff0c;要点如下 近1年A股风格因子收益走…

2023年最新电商某东app端sign签名算法与cipher加解密逆向分析(2023-09-26)

前言&#xff1a; 本文仅供学习交流&#xff0c;只提供关键思路不会给出完整代码&#xff0c;严禁用于非法用途&#xff0c;若有侵权请联系我删除&#xff01;技术交流合作请私信&#xff01; 一.工具的选择&#xff08;抓包工具的选择&#xff0c;是门学问&#xff09; 用…

智能交通RFID设备的实际应用有哪些?

随着RFID应用的不断普及&#xff0c;交通系统中也引入了RFID来用作车辆的识别和监控&#xff0c;如我们常见的车辆前挡风玻璃内侧安装的RFID电子标签进行通信&#xff0c;可以实现对车辆的自动、非接触、不停车识别和监控。下面我们就一起来了解一下&#xff0c;智能交通RFID设…

《学术小白学习之路11》DTM主题动态模型原理与基础构建

《学术小白学习之路》DTM主题动态模型构建 一、LDA与DTM的区别二、代码实操2.1 数据2.2 获取数据向量2.3 参数设置与模型构建2.4 结果的输出一、LDA与DTM的区别 LDA主题模型主要针对一段段的文档 可以得出每个主题,所对应主题词的词语的概率 该模型的主题概率的生成是基于文…

大规模语言模型的模型结构---编码器-解码器结构(GLM,UL2系列)

2020 年 Open AI 发布了由包含 1750 亿参数的神经网络构成的生成式大规模预训练语言模型 GPT-3 (Gener- ative Pre-trained Transformer 3)。开启了大规模语言模型的新时代。由于大规模语言模型的参数量巨大&#xff0c; 如果在 不同任务上都进行微调需要消耗大量的计算资源&a…

单元测试、集成测试、系统测试到底有什么不同?

单元测试、集成测试和系统测试是软件测试开发中不可或缺的部分。 单元测试 范围&#xff1a;单元测试是对软件中最小的可测试单元的测试&#xff0c;通常是函数、方法或类。 目的&#xff1a;它的目标是验证每个单独的单元是否按照预期工作&#xff0c;以增加代码的可靠性和稳…

斩获双奖!人大金仓亮相第六届智慧医疗创新大赛全国总决赛

9月22日&#xff0c;2023数字健康创新大会暨第六届智慧医疗创新大赛全国总决赛圆满结束。凭借在智慧医疗领域的创新成果&#xff0c;人大金仓荣获“最佳原创奖”以及医疗信创赛道“二等奖”&#xff0c;获得业内专家、用户、相关单位领导及医疗伙伴的高度认可。 获奖证书 左右滑…

MySQL的时间差函数、日期转换计算函数

MySQL的时间差函数(TIMESTAMPDIFF、DATEDIFF)、日期转换计算函数(date_add、day、date_format、str_to_date) 时间差函数&#xff08;TIMESTAMPDIFF、DATEDIFF&#xff09; 需要用MySQL计算时间差&#xff0c;使用TIMESTAMPDIFF、DATEDIFF&#xff0c;记录一下实验结果 --0 …

如何学习maya mel语言的经验分享

一、前言 总结一下这十几年来学习和使用mel语言的一些经验&#xff0c;供初学朋参考&#xff0c;哈哈。 这里不说深奥理论&#xff0c;只是朴实经历陈述。 其实&#xff0c;早在2003年&#xff0c;最初接触maya时&#xff0c;就已经涉及到mel的学习&#xff0c;当时在大学里接…