Linux网络编程(socket)

1. 概念

局域网和广域网

  • 局域网:局域网将一定区域内的各种计算机、外部设备和数据库连接起来形成计算机通信的私有网络。
  • 广域网:又称广域网、外网、公网。是连接不同地区局域网或城域网计算机通信的远程公共网络。

IP(Internet Protocol):本质是一个整形数,用于表示计算机在网络中的地址。IP协议版本有两个:IPv4和IPv6

  • IPv4(Internet Protocol version4):使用一个32位的整形数描述一个IP地址,4个字节,int型,也可以使用一个点分十进制字符串描述这个IP地址: 192.168.247.135。分成了4份,每份1字节,8bit(char),最大值为 255;0.0.0.0 是最小的IP地址;255.255.255.255是最大的IP地址;按照IPv4协议计算,可以使用的IP地址共有 232 个
  • IPv6(Internet Protocol version6):使用一个128位的整形数描述一个IP地址,16个字节,也可以使用一个字符串描述这个IP地址:2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b;分成了8份,每份2字节,每一部分以16进制的方式表示;按照IPv6协议计算,可以使用的IP地址共有 2128 个

查看IP地址

# linux
$ ifconfig

# windows
$ ipconfig

# 测试网络是否畅通
# 主机a: 192.168.1.11
# 当前主机: 192.168.1.12
$ ping 192.168.1.11     # 测试是否可用连接局域网
$ ping www.baidu.com    # 测试是否可用连接外网

# 特殊的IP地址: 127.0.0.1  ==> 和本地的IP地址是等价的
# 假设当前电脑没有联网, 就没有IP地址, 又要做网络测试, 可用使用 127.0.0.1 进行本地测试

        端口:端口的作用是定位到主机上的某一个进程,通过这个端口进程就可以接受到对应的网络数据了。

        比如: 在电脑上运行了微信和QQ, 小明通过客户端给我的的微信发消息, 电脑上的微信就收到了消息, 为什么?

  • 运行在电脑上的微信和QQ都绑定了不同的端口
  • 通过IP地址可以定位到某一台主机,通过端口就可以定位到主机上的某一个进程
  • 通过指定的IP和端口,发送数据的时候对端就能接受到数据了

        端口也是一个整形数 unsigned short ,一个16位整形数,有效端口的取值范围是:0 ~ 65535(0 ~ 216-1)

提问:计算机中所有的进程都需要关联一个端口吗,一个端口可以被重复使用吗?

  • 不需要,如果这个进程不需要网络通信,那么这个进程就不需要绑定端口的
  • 一个端口只能给某一个进程使用,多个进程不能同时使用同一个端口

        OSI/ISO 网络分层模型:OSI(Open System Interconnect),即开放式系统互联。 一般都叫OSI参考模型,是ISO(国际标准化组织组织)在1985年研究的网络互联模型。

  • 1. 物理层(Physical layer):负责传输比特流,将数据转化为适合在物理媒介上传输的电信号,如网线、光纤等。
  • 2. 数据链路层(Data Link layer):提供可靠的数据传输,将物理层传输的比特流组织为帧(Frame),并通过检验和等方式进行错误检测和纠正。
  • 3. 网络层(Network layer):实现网络互连和数据路由,负责确定数据的传输路径,并将数据包(Packet)从源节点传输到目标节点。
  • 4. 传输层(Transport layer):负责为应用程序提供端到端的通信服务,包括可靠的数据传输和数据分段重组,常见的协议如TCP和UDP。
  • 5. 会话层(Session layer):负责建立、管理和终止应用程序之间的会话连接,包括控制会话的建立、同步和终止等操作。
  • 6. 表示层(Presentation layer):负责数据的格式转换、加密解密和压缩解压缩等操作,以确保应用程序能够正确解释和处理接收到的数据。
  • 7. 应用层(Application layer):提供用户应用程序与网络之间的接口,包括文件传输、电子邮件、网页浏览等各种应用服务。

        这七层协议组成了一个通用的网络模型,每一层都具有不同的功能和责任,通过协同工作实现了数据在计算机网络中的可靠传输和应用程序之间的交互。请注意,实际的网络协议栈(如TCP/IP)并不完全符合OSI模型,但是OSI模型仍然被广泛用于理解和教学网络概念。

2. 网络协议

        网络协议是计算机网络中用于在不同计算机之间进行数据传输和交换的规则和约定。它定义了数据如何在网络中传输、如何组织和解释数据以及如何处理错误和冲突等情况。常见的网络协议包括:

  • 1. TCP/IP协议:是互联网的核心协议,包括传输控制协议(TCP)和Internet协议(IP)。TCP提供可靠的数据传输,确保数据的完整性和有序性;IP负责数据包的路由和寻址。
  • 2. HTTP协议:是用于在Web上进行超文本传输的协议,定义了客户端和服务器之间的通信规则。常用于浏览器和服务器之间传输网页、图片和其他资源。
  • 3. FTP协议:是文件传输协议,用于在客户端和服务器之间进行文件传输。它支持上传、下载、删除和重命名等操作。
  • 4. SMTP协议:是简单邮件传输协议,用于在邮件服务器之间传输电子邮件。它定义了邮件的格式和传输规则。
  • 5. POP协议和IMAP协议:是接收邮件的协议,用于从邮件服务器中接收电子邮件。POP协议通常会将邮件下载到本地设备,而IMAP协议则保留邮件在服务器上,以便在不同设备上同步访问邮件。
  • 6. DNS协议:是域名系统协议,用于将域名(如www.example.com)转换为对应的IP地址。它提供了域名解析和IP地址管理的功能。
  • 7. DHCP协议:是动态主机配置协议,用于在局域网中自动分配IP地址给计算机和其他设备。它还提供了其他网络配置信息,如子网掩码、网关和DNS服务器等。

        这些协议在计算机网络中发挥着重要的作用,实现了可靠的数据传输、资源共享、电子邮件通信和互联网的基本功能。不同的协议在不同层次上工作,并相互配合以实现全面的网络通信。

3. socket编程

        Socket编程是一种用于在计算机网络之间进行通信的编程技术。它基于TCP/IP协议栈,允许不同计算机之间的进程通过网络进行数据传输和交互。
        通过Socket编程,可以实现客户端和服务器之间的通信。客户端可以向服务器发送请求,服务器则可以对这些请求进行响应。Socket编程使用网络套接字(socket)作为通信的端点,允许进程在网络上发送和接收数据。
        在Socket编程中,存在两种常见类型的套接字:客户端套接字和服务器套接字。客户端套接字用于连接服务器并发送请求,而服务器套接字用于侦听客户端连接并处理请求。
        Socket编程可以用于构建各种网络应用程序,例如网络聊天程序、文件传输程序、Web服务器等。编程语言如Python、Java和C++都提供了Socket编程的库和API,使开发者能够方便地使用Socket进行网络通信。
        需要注意的是,Socket编程涉及到网络通信和数据传输,因此在实际使用中需要考虑网络连接的稳定性、数据的完整性和安全性等方面的问题。

3.1 字节序

        在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元(比特、字节、字、双字等等)应该以什么样的顺序进行传送。如果不达成一致的规则,通信双方将无法进行正确的编/译码从而导致通信失败。

        字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,也就是说对于单字符来说是没有字节序问题的,字符串是单字符的集合,因此字符串也没有字节序问题。

        目前在各种体系的计算机中通常采用的字节存储机制主要有两种:Big-Endian 和 Little-Endian,下面先从字节序说起。

  • Little-Endian -> 主机字节序 (小端):数据的低位字节存储到内存的低地址位, 数据的高位字节存储到内存的高地址位,我们使用的PC机,数据的存储默认使用的是小端
  • Big-Endian -> 网络字节序 (大端):据的低位字节存储到内存的高地址位, 数据的高位字节存储到内存的低地址位,套接字通信过程中操作的数据都是大端存储的,包括:接收/发送的数据、IP地址、端口。

字节序举例

// 有一个16进制的数, 有32位 (int): 0xab5c01ff
// 字节序, 最小的单位: char 字节, int 有4个字节, 需要将其拆分为4份
// 一个字节 unsigned char, 最大值是 255(十进制) ==> ff(16进制) 
                 内存低地址位                内存的高地址位
--------------------------------------------------------------------------->
小端:         0xff        0x01        0x5c        0xab
大端:         0xab        0x5c        0x01        0xff

函数:

        BSD Socket提供了封装好的转换接口,方便程序员使用。包括从主机字节序到网络字节序的转换函数:htons、htonl;从网络字节序到主机字节序的转换函数:ntohs、ntohl。

#include <arpa/inet.h>
// u:unsigned
// 16: 16位, 32:32位
// h: host, 主机字节序
// n: net, 网络字节序
// s: short
// l: int

// 这套api主要用于 网络通信过程中 IP 和 端口 的 转换
// 将一个短整形从主机字节序 -> 网络字节序
uint16_t htons(uint16_t hostshort);	
// 将一个整形从主机字节序 -> 网络字节序
uint32_t htonl(uint32_t hostlong);	

// 将一个短整形从网络字节序 -> 主机字节序
uint16_t ntohs(uint16_t netshort)
// 将一个整形从网络字节序 -> 主机字节序
uint32_t ntohl(uint32_t netlong);

3.2 IP地址转换

        虽然IP地址本质是一个整形数,但是在使用的过程中都是通过一个字符串来描述,下面的函数描述了如何将一个字符串类型的IP地址进行大小端转换:

// 主机字节序的IP地址转换为网络字节序
// 主机字节序的IP地址是字符串, 网络字节序IP地址是整形
int inet_pton(int af, const char *src, void *dst); 

参数:

  • af: 地址族(IP地址的家族包括ipv4和ipv6)协议
    • AF_INET: ipv4格式的ip地址
    • AF_INET6: ipv6格式的ip地址
  • src: 传入参数, 对应要转换的点分十进制的ip地址: 192.168.1.100
  • dst: 传出参数, 函数调用完成, 转换得到的大端整形IP被写入到这块内存中

返回值:成功返回1,失败返回0或者-1

#include <arpa/inet.h>
// 将大端的整形数, 转换为小端的点分十进制的IP地址        
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

参数:

  • af: 地址族协议
    • AF_INET: ipv4格式的ip地址
    • AF_INET6: ipv6格式的ip地址
  • src: 传入参数, 这个指针指向的内存中存储了大端的整形IP地址
  • dst: 传出参数, 存储转换得到的小端的点分十进制的IP地址
  • size: 修饰dst参数的, 标记dst指向的内存中最多可以存储多少个字节

返回值:

  • 成功: 指针指向第三个参数对应的内存地址, 通过返回值也可以直接取出转换得到的IP字符串
  • 失败: NULL

还有一组函数也能进程IP地址大小端的转换,但是只能处理ipv4的ip地址:

// 点分十进制IP -> 大端整形
in_addr_t inet_addr (const char *cp);

// 大端整形 -> 点分十进制IP
char* inet_ntoa(struct in_addr in);

3.3 sockaddr 数据结构

// 在写数据的时候不好用
struct sockaddr {
	sa_family_t sa_family;       // 地址族协议, ipv4
	char        sa_data[14];     // 端口(2字节) + IP地址(4字节) + 填充(8字节)
}

typedef unsigned short  uint16_t;
typedef unsigned int    uint32_t;
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))

struct in_addr
{
    in_addr_t s_addr;
};  

// sizeof(struct sockaddr) == sizeof(struct sockaddr_in)
struct sockaddr_in
{
    sa_family_t sin_family;		/* 地址族协议: AF_INET */
    in_port_t sin_port;         /* 端口, 2字节-> 大端  */
    struct in_addr sin_addr;    /* IP地址, 4字节 -> 大端  */
    /* 填充 8字节 */
    unsigned char sin_zero[sizeof (struct sockaddr) - sizeof(sin_family) -
               sizeof (in_port_t) - sizeof (struct in_addr)];
};  

3.4 套接字函数

        使用套接字通信函数需要包含头文件<arpa/inet.h>,包含了这个头文件<sys/socket.h>就不用在包含了。

// 创建一个套接字
int socket(int domain, int type, int protocol);

参数:
domain: 使用的地址族协议

  • AF_INET: 使用IPv4格式的ip地址
  • AF_INET6: 使用IPv4格式的ip地址

type:

  • SOCK_STREAM: 使用流式的传输协议
  • SOCK_DGRAM: 使用报式(报文)的传输协议

protocol: 一般写0即可, 使用默认的协议

  • SOCK_STREAM: 流式传输默认使用的是tcp
  • SOCK_DGRAM: 报式传输默认使用的udp

返回值:

  • 成功: 可用于套接字通信的文件描述符
  • 失败: -1

        函数的返回值是一个文件描述符,通过这个文件描述符可以操作内核中的某一块内存,网络通信是基于这个文件描述符来完成的。

// 将文件描述符和本地的IP与端口进行绑定   
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数:

  • sockfd: 监听的文件描述符, 通过socket()调用得到的返回值
  • addr: 传入参数, 要绑定的IP和端口信息需要初始化到这个结构体中,IP和端口要转换为网络字节序
  • addrlen: 参数addr指向的内存大小, sizeof(struct sockaddr)

返回值:成功返回0,失败返回-1

// 给监听的套接字设置监听
int listen(int sockfd, int backlog);

参数:

  • sockfd: 文件描述符, 可以通过调用socket()得到,在监听之前必须要绑定 bind()
  • backlog: 同时能处理的最大连接要求,最大值为128

返回值:函数调用成功返回0,调用失败返回 -1

// 等待并接受客户端的连接请求, 建立新的连接, 会得到一个新的文件描述符(通信的)		
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数:

  • sockfd: 监听的文件描述符
  • addr: 传出参数, 里边存储了建立连接的客户端的地址信息
  • addrlen: 传入传出参数,用于存储addr指向的内存大小

返回值:函数调用成功,得到一个文件描述符, 用于和建立连接的这个客户端通信,调用失败返回 -1
        这个函数是一个阻塞函数,当没有新的客户端连接请求的时候,该函数阻塞;当检测到有新的客户端连接请求时,阻塞解除,新连接就建立了,得到的返回值也是一个文件描述符,基于这个文件描述符就可以和客户端通信了。

// 接收数据
ssize_t read(int sockfd, void *buf, size_t size);
ssize_t recv(int sockfd, void *buf, size_t size, int flags);

参数:

  • sockfd: 用于通信的文件描述符, accept() 函数的返回值
  • buf: 指向一块有效内存, 用于存储接收是数据
  • size: 参数buf指向的内存的容量
  • flags: 特殊的属性, 一般不使用, 指定为 0

返回值:

  • 大于0:实际接收的字节数
  • 等于0:对方断开了连接
  • -1:接收数据失败了

        如果连接没有断开,接收端接收不到数据,接收数据的函数会阻塞等待数据到达,数据到达后函数解除阻塞,开始接收数据,当发送端断开连接,接收端无法接收到任何数据,但是这时候就不会阻塞了,函数直接返回0。

// 发送数据的函数
ssize_t write(int fd, const void *buf, size_t len);
ssize_t send(int fd, const void *buf, size_t len, int flags);

参数:

  • fd: 通信的文件描述符, accept() 函数的返回值
  • buf: 传入参数, 要发送的字符串
  • len: 要发送的字符串的长度
  • flags: 特殊的属性, 一般不使用, 指定为 0

返回值:

  • 大于0:实际发送的字节数,和参数len是相等的
  • -1:发送数据失败了
// 成功连接服务器之后, 客户端会自动随机绑定一个端口
// 服务器端调用accept()的函数, 第二个参数存储的就是客户端的IP和端口信息
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数:

  • sockfd: 通信的文件描述符, 通过调用socket()函数就得到了
  • addr: 存储了要连接的服务器端的地址信息: iP 和 端口,这个IP和端口也需要转换为大端然后再赋值
  • addrlen: addr指针指向的内存的大小 sizeof(struct sockaddr)

返回值:连接成功返回0,连接失败返回-1

4. TCP通信流程

TCP是一个面向连接的,安全的,流式传输协议,这个协议是一个传输层协议。

  • 面向连接:是一个双向连接,通过三次握手完成,断开连接需要通过四次挥手完成。
  • 安全:tcp通信过程中,会对发送的每一数据包都会进行校验, 如果发现数据丢失, 会自动重传
  • 流式传输:发送端和接收端处理数据的速度,数据的量都可以不一致

4.1 服务器端通信流程

1. 创建用于监听的套接字, 这个套接字是一个文件描述符

int lfd = socket();

2. 将得到的监听的文件描述符和本地的IP 端口进行绑定

bind();

3. 设置监听(成功之后开始监听, 监听的是客户端的连接)

listen();

4. 等待并接受客户端的连接请求, 建立新的连接, 会得到一个新的文件描述符(通信的),没有新连接请求就阻塞

int cfd = accept();

5. 通信,读写操作默认都是阻塞的

// 接收数据
read(); / recv();
// 发送数据
write(); / send();

6. 断开连接, 关闭套接字

close();

在tcp的服务器端, 有两类文件描述符

监听的文件描述符

  • 只需要有一个
  • 不负责和客户端通信, 负责检测客户端的连接请求, 检测到之后调用accept就可以建立新的连接

通信的文件描述符

  • 负责和建立连接的客户端通信
  • 如果有N个客户端和服务器建立了新的连接, 通信的文件描述符就有N个,每个客户端和服务器都对应一个通信的文件描述符

文件描述符对应的内存结构:

  • 一个文件文件描述符对应两块内存, 一块内存是读缓冲区, 一块内存是写缓冲区
  • 读数据: 通过文件描述符将内存中的数据读出, 这块内存称之为读缓冲区
  • 写数据: 通过文件描述符将数据写入到某块内存中, 这块内存称之为写缓冲区

监听的文件描述符:

  • 客户端的连接请求会发送到服务器端监听的文件描述符的读缓冲区中
  • 读缓冲区中有数据, 说明有新的客户端连接
  • 调用accept()函数, 这个函数会检测监听文件描述符的读缓冲区
    • 检测不到数据, 该函数阻塞
    • 如果检测到数据, 解除阻塞, 新的连接建立

通信的文件描述符:

  • 客户端和服务器端都有通信的文件描述符
  • 发送数据:调用函数 write() / send(),数据进入到内核中
    • 数据并没有被发送出去, 而是将数据写入到了通信的文件描述符对应的写缓冲区中
    • 内核检测到通信的文件描述符写缓冲区中有数据, 内核会将数据发送到网络中
  • 接收数据: 调用的函数 read() / recv(), 从内核读数据
    • 数据如何进入到内核程序猿不需要处理, 数据进入到通信的文件描述符的读缓冲区中
    • 数据进入到内核, 必须使用通信的文件描述符, 将数据从读缓冲区中读出即可

基于tcp的服务器端通信代码:

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

int main()
{
    // 1. 创建监听的套接字
    int lfd = socket(AF_INET, SOCK_STREAM, 0);
    if(lfd == -1)
    {
        perror("socket");
        exit(0);
    }

    // 2. 将socket()返回值和本地的IP端口绑定到一起
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(10000);   // 大端端口
    // INADDR_ANY代表本机的所有IP, 假设有三个网卡就有三个IP地址
    // 这个宏可以代表任意一个IP地址
    // 这个宏一般用于本地的绑定操作
    addr.sin_addr.s_addr = INADDR_ANY;  // 这个宏的值为0 == 0.0.0.0
//    inet_pton(AF_INET, "192.168.237.131", &addr.sin_addr.s_addr);
    int ret = bind(lfd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret == -1)
    {
        perror("bind");
        exit(0);
    }

    // 3. 设置监听
    ret = listen(lfd, 128);
    if(ret == -1)
    {
        perror("listen");
        exit(0);
    }

    // 4. 阻塞等待并接受客户端连接
    struct sockaddr_in cliaddr;
    int clilen = sizeof(cliaddr);
    int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &clilen);
    if(cfd == -1)
    {
        perror("accept");
        exit(0);
    }
    // 打印客户端的地址信息
    char ip[24] = {0};
    printf("客户端的IP地址: %s, 端口: %d\n",
           inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, ip, sizeof(ip)),
           ntohs(cliaddr.sin_port));

    // 5. 和客户端通信
    while(1)
    {
        // 接收数据
        char buf[1024];
        memset(buf, 0, sizeof(buf));
        int len = read(cfd, buf, sizeof(buf));
        if(len > 0)
        {
            printf("客户端say: %s\n", buf);
            write(cfd, buf, len);
        }
        else if(len  == 0)
        {
            printf("客户端断开了连接...\n");
            break;
        }
        else
        {
            perror("read");
            break;
        }
    }

    close(cfd);
    close(lfd);

    return 0;
}

4.2 客户端通信流程

在单线程的情况下客户端通信的文件描述符有一个, 没有监听的文件描述符

1. 创建一个通信的套接字

int cfd = socket();

2. 连接服务器, 需要知道服务器绑定的IP和端口

connect();

3. 通信

// 接收数据
read(); / recv();
// 发送数据
write(); / send();

4. 断开连接, 关闭文件描述符(套接字)

close();

基于tcp通信的客户端通信代码:

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

int main()
{
    // 1. 创建通信的套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1)
    {
        perror("socket");
        exit(0);
    }

    // 2. 连接服务器
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(10000);   // 大端端口
    inet_pton(AF_INET, "192.168.237.131", &addr.sin_addr.s_addr);

    int ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret == -1)
    {
        perror("connect");
        exit(0);
    }

    // 3. 和服务器端通信
    int number = 0;
    while(1)
    {
        // 发送数据
        char buf[1024];
        sprintf(buf, "你好, 服务器...%d\n", number++);
        write(fd, buf, strlen(buf)+1);
        
        // 接收数据
        memset(buf, 0, sizeof(buf));
        int len = read(fd, buf, sizeof(buf));
        if(len > 0)
        {
            printf("服务器say: %s\n", buf);
        }
        else if(len  == 0)
        {
            printf("服务器断开了连接...\n");
            break;
        }
        else
        {
            perror("read");
            break;
        }
        sleep(1);   // 每隔1s发送一条数据
    }

    close(fd);

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【计算机网络原理】对传输层TCP协议的重点知识的总结

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

【B站 heima】小兔鲜Vue3 项目学习笔记Day04

文章目录 二级分类1.整体认识和路由配置2.面包屑导航功能实现3. 基础商品列表实现4. 定制路由滚动行为 详情页1.整体认识和路由配置2.基础数据渲染3.热榜区域实现4. 图片预览组件封装5.放大镜-滑块跟随移动左侧滑块跟随鼠标移动放大镜-大图效果 6. props适配7. SKU组件熟悉使用…

vue3项目+TypeScript前端项目 ———— elemnet-plus,svg图标配置,sass,mock数据

一.集成element-plus 官网地址 安装 pnpm install element-plus 引入 // main.ts import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import App from ./App.vueconst app createApp(App)app.use(ElementPlus) app.…

气膜建筑的工作原理与优势解析—轻空间

近年来&#xff0c;气膜建筑凭借其独特的结构设计和诸多优点&#xff0c;迅速成为建筑领域的热门选择。本文将详细介绍气膜建筑的工作原理、机械系统、智能控制、索网控制和空气净化等方面&#xff0c;为您提供全面了解气膜建筑的基础知识。 气膜建筑的工作原理 气膜建筑是一种…

01 FreeRTOS 初识

1、freeRTOS 1.1 什么是FreeRTOS Free就是免费的&#xff0c;RTOS全称是real time operating system&#xff0c;即实时操作系统。FreeRTOS是一个迷你的实时操作系统内核&#xff0c;作为一个轻量级的操作系统&#xff0c;功能包括&#xff1a;任务管理、时间管理、信号量、消…

【AI基础】反向传播

文章目录 1. 先写出第一步2.将其封装成函数3. pytorch版 1. 先写出第一步 # 定义输入值和期望输出 x_1 40.0 x_2 80.0 expected_output 60.0 初始化# 定义权重 w_1_11 0.5 w_1_12 0.5 w_1_13 0.5 w_1_21 0.5 w_1_22 0.5 w_1_23 0.5w_2_11 1.0 w_2_21 1.0 w_2_31 1…

RocketMQ实战教程之RocketMQ安装(含Docker安装,建议收藏!)

RocketMQ实战教程之RocketMQ安装 这里实例采用centos系统天翼云为例,分别采用传统安装以及Docker安装的方式来进行RocketMQ的安装.JDK8我这边已经安装配置好了,这里就不在赘述.直接进入正题: 传统安装包安装 系统要求 64位操作系统&#xff0c;推荐 Linux/Unix/macOS64位 JDK…

Java 对外API接口开发 java开发api接口如何编写

Java API API&#xff08;Application Programming Interface&#xff09;是指应用程序编程接口&#xff0c;的JavaAPI是指JDK提供的各种功能的Java类 String类 String类的初始化&#xff1a; &#xff08;1&#xff09;使用字符串常量直接初始化 初始化&#xff1a;String s…

第11章 集合与迭代器

目录 目录 目录 11.1 Collection集合 11.1.1 集合的概念 11.1.2 Collection接口 1、添加元素 2、删除元素 3、查询与获取元素 11.2 List 有序集合 11.2.1 新增方法 11.2.2 ArrayList 11.2.3 LinkedList 1、单向链表 2、双向链表 3、删除元素 11.3 Set 无序集合 …

深度学习-转置卷积

转置卷积 转置卷积&#xff08;Transposed Convolution&#xff09;&#xff0c;也被称为反卷积&#xff08;Deconvolution&#xff09;&#xff0c;是深度学习中的一种操作&#xff0c;特别是在卷积神经网络&#xff08;CNN&#xff09;中。它可以将一个低维度的特征图&#x…

深入 Rust 标准库,Rust标准库源代码系统分析

系列文章目录 送书第一期 《用户画像&#xff1a;平台构建与业务实践》 送书活动之抽奖工具的打造 《获取博客评论用户抽取幸运中奖者》 送书第二期 《Spring Cloud Alibaba核心技术与实战案例》 送书第三期 《深入浅出Java虚拟机》 送书第四期 《AI时代项目经理成长之道》 …

智能猫眼锁核心解决方案以及芯片简介SSD222

书接上回&#xff0c;前篇文章我们诠释了IP 网络摄像系统的定义以及组成部分的功能&#xff0c;也大概的讲了一下所针对的市场以及举例介绍了一款相关芯片&#xff0c;详情可点击下面卡片浏览高集成IP摄像SOC处理方案简介https://blog.csdn.net/Chipsupply/article/details/139…

PDF Reader Pro for Mac 直装激活版:专业PDF阅读编辑软件

在数字化时代&#xff0c;PDF文件已成为我们日常工作和学习中不可或缺的一部分。然而&#xff0c;如何高效、便捷地阅读、编辑和管理这些PDF文件&#xff0c;却一直是许多人面临的难题。现在&#xff0c;有了PDF Reader Pro for Mac&#xff0c;这些难题将迎刃而解。 PDF Reade…

谷歌快速收录怎么做?

快速收录顾名思义&#xff0c;就是让新的的网页内容能够迅速被谷歌搜索引擎抓取、索引和显示在搜索结果中&#xff0c;这对于做seo来说非常重要&#xff0c;因为它有助于新发布的内容尽快出现在谷歌的搜索结果中&#xff0c;从而增加网站的流量 想做谷歌快速收录谷歌推荐了几种…

AD162A低功耗语音解码芯片,助眠耳机方案推荐—云信通讯

睡眠一直是很多人所追寻的目标&#xff0c;无论是因为工作压力过大&#xff0c;还是日常烦扰的思绪&#xff0c;一个好的睡眠质量对每个人来说都至关重要。为了解决这个问题&#xff0c;一些科技公司开发了高品质的助眠耳机&#xff0c;通过音乐和声音来帮助入睡&#xff0c;为…

华为大咖说 | 企业应用AI大模型的“道、法、术” ——道:认知篇

本文作者&#xff1a;郑岩&#xff08;华为云AI变革首席专家&#xff09;全文约3313字&#xff0c;阅读约需8分钟&#xff0c;请仔细看看哦~ 前阵子&#xff0c;我在公司内部发了一篇Sora的科普贴&#xff0c;本来只是个简单的技术总结&#xff0c;但让我意外的是&#xff0c;…

linux系统安全加固

目录 1、账户安全基本措施 1&#xff09;系统账户清理 2&#xff09;密码安全控制 3&#xff09;命令历史限制 2、用户切换及提权 1&#xff09;使用 su命令切换用户 2&#xff09;使用sudo机制提升权限 3、系统引导和安全登录控制 1&#xff09;开机安全控制 2&…

docker如何拉取nginx最新镜像并运行

要拉取Docker Hub上的最新Nginx镜像&#xff0c;您可以使用以下命令&#xff1a; docker pull nginx 这个命令会从Docker Hub下载最新版本的Nginx镜像。如果您想要拉取特定版本的Nginx镜像&#xff0c;可以指定版本号&#xff0c;例如&#xff1a; docker pull nginx:1.18.0 拉…

实在智能签约世界机械500强特变电工 ,加速能源装备巨头智能化升级

近日&#xff0c;世界机械500强、中国企业500强特变电工集团正式与实在智能达成战略合作&#xff0c;由实在智能为其部署RPA数字员工解决方案&#xff0c;助力集团公司各级财务部门提升自动化水平&#xff0c;进一步实现集团内降本增效目标。 关于特变电工 特变电工是国家级高…

AI工具推荐:提升工作效率与生活质量

有哪些好用&#xff0c;且国内可用的AI工具&#xff1f; 副本 在AI大发展的年代&#xff0c;还有人在工作、生活中没有使用过AI吗&#xff1f; 今天为大家推荐几款国内可用、好用的AI工具&#xff0c;不论是自媒体文案写作、打工人汇报PPT、还是论文、公文写作&#xff0c;总…