网络基础-PosixAPI

news2024/12/28 5:24:26

文章目录

  • 一.网络常用接口
    • Linux协议栈与posix api的关系 背景
    • 1.1 socket
    • 1.8 close
    • 服务端posix接口
    • 1.2 bind
    • 1.3 listen
    • 1.4 accept
    • 1.5 connect
    • 1.6 send
    • 1.7 recv
    • 总结
  • 二. 修改句柄属性
    • 2.1 fctl
    • 2.2 特殊作用
    • 2.2.1 设置阻塞非阻塞
    • 2.2.1 实例
      • 2.2.2设置获取记录锁
      • 2.2.2 实例
  • 三、文件操作函数
    • 3.1 相关接口函数
      • fwrite() 函数
      • fread() 函数
      • fclose()函数
      • fflush()函数
      • fsync()函数
      • setbuf()函数
      • write()函数
  • 参考

一.网络常用接口

Linux协议栈与posix api的关系 背景

众所周知,Linux内核协议栈Linux内核的网络管理模块的具象化表达实例,用户空间如果想使用Linux内核提供的网络服务就需要使用内核提供的一系列网络相关的posix接口(操作系统原语,或者说原生接口)。

以TCP通信举例,我们想开发一套基于C/S通信架构的服务,需要获取一个tcp的socket,该socket本质上是一个文件描述符,也可以说是一个内核中tcb(tcp control block)的映射。当我们在应用层调用connect,send等posix相关的api(系统调用)时,内核就会操作tcb的传输内存,按照tcp协议的标准,进行握手建立连接并发送用户数据。

网络开发必用结构体
通过struct sockaddr_in结构体指定协议族,指定绑定地址,指定监控的端口号。
使用的成员:sin_family、sin_addr.s_addr、sin_port;

1.1 socket

socket:

#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain, int type, int protocol);

这个函数建立一个协议族、协议类型、协议编号的socket文件描述符。如果函数调用成功,会返回一个标识这个套接字的文件描述符,失败的时候返回-1。

domain参数值含义:
名称 含义
PF_UNIX,PF_LOCAL 本地通信
AF_INET,PF_INET IPv4协议
PF_INET6 IPv6协议
PF_NETLINK 内核用户界面设备
PF_PACKET 底层包访问

type参数值含义:

名称 含义
SOCK_STREAM TCP连接,提供序列化的、可靠的、双向连接的字节流。支持带外数据传输
SOCK_DGRAM UDP连接
SOCK_SEQPACKET 序列化包,提供一个序列化的、可靠的、双向的数据传输通道,数据长度定常。每次调用读系统调用时数据需要将全部数据读出
:SOCK_PACKET 专用类型
SOCK_RDM 提供可靠的数据报文,不保证数据有序
SOCK_RAW 提供原始网络协议访问
protocol参数含义:
通常某协议中只有一种特定类型,这样protocol参数仅能设置为0;如果协议有多种特定的类型,就需要设置这个参数来选择特定的类型。

1.8 close

该接口用于关闭套接字,当应用程序调用close函数关闭套接字时,内核会释放该套接字所占用的资源,并将其从内核数据结构中移除。
接口也很简单,直接close(sockfd)即可。

服务端posix接口

1.2 bind

bind

#include<sys/types.h>
#include<sys/socket.h>
int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);

参数说明:
第1个参数sockfd是用socket()函数创建的文件描述符。
第2个参数my_addr是指向一个结构为sockaddr参数的指针,sockaddr中包含了地址、端口和IP地址的信息。
第3个参数addrlen是my_addr结构的长度,可以设置成sizeof(struct sockaddr)。
bind()函数的返回值为0时表示绑定成功,-1表示绑定失败

1.3 listen

listen

#include<sys/socket.h>
int listen(int sockfd, int backlog);

@sockfd  创建的socket 返回的文件描述符
@return 返回值:若成功,返回 0;若出错,返回-1

参数说明:
第1个参数sockfd是用socket()函数创建的文件描述符。
第2个参数规定了内核应该为相应套接字排队的最大连接个数。

分析
服务端调用listen宣告它接受连接请求,其参数backlog提供了一个提示,提示该进程所要入队的未完成连接的请求数量。为什么说是提示呢,因为根据Linux内核的不断迭代,实际上该socket可以容纳的未连接请求远远不止传入的这个数目,其数量可以自适应增加,但不会超过其上限:<sys/socket.h>中的SOMAXCONN

1.4 accept

服务端调用了listen让主动套接字变被动监听套接字,就可以使用accept函数获得连接请求并建立连接;

accept

#include<sys/types.h>
#include<sys/socket.h>
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

@sockfd:服务端socket,该socket仅用于接收连接请求,获取的新socket的fd与之无关。
@addr:一个指向struct sockaddr类型变量的指针,用于存储客户端地址信息。
@len:一个指向socklen_t类型变量的指针,表示addr结构体长度。
@return 返回值:若成功,返回文件 (套接字) 描述符;若出错,返回-1

参数说明:
sockefd:套接字描述符,该套接字在listen()后监听连接。
addr:(可选)指针。组客户端结构体 指向一个缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。
addrlen:(可选)指针。输入参数,配合addr一起使用,指向存有addr地址长度的整形数。

分析:
当服务器程序调用accept()时,如果此时有客户端发送了连接请求,那么它将立即从内核中已经建立的全连接队列中,寻找该请求的五元组信息。如果确认该客户端已经处于全连接队列,那么就返回新分配给该客户端所用的套接字文件描述符。

此时服务器进程就可以利用该文件描述符与该客户进程进行通信了。同时,在accept()函数中会填充传入参数中对应结构体(如addr)的内容,以获得远程主机地址信息等相关信息。

注意

  1. 当没有连接请求到达时,accept()函数会一直阻塞等待,并且只有在监听套接字上有连接请求时,它才会返回新的套接字描述符,可以将socket设置为非阻塞从而马上获得获取结果。(此时服务器状态已经编程被动)
  2. 由于accept()函数是阻塞式函数,因此可能会导致服务器程序被挂起,为了避免这种情况的出现,可以通过使用多线程或者多路复用等技术来实现同时处理多个客户端请求。
  3. accept()函数只能用于监听TCP协议的连接请求,不能用于UDP协议。

1.5 connect

connect

1.6 send

#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);

参数说明:
sockfd:向套接字中发送数据
buf:要发送的数据的首地址
len:要发送的数据的字节
int flags:设置为MSG_DONTWAITMSG 时 表示非阻塞,设置为0时 功能和write一样
返回值:成功返回实际发送的字节数,失败返回 -1

1.7 recv

#include<sys/types.h>
#include<sys/socket.h>
int recv( int fd, char *buf, int len, int flags);

参数说明:
第一个参数指定接收端套接字描述符;
第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
第三个参数指明buf的长度;
第四个参数一般置0。

在非阻塞状态下,recv 返回值处理!

在非阻塞状态下,recv() 接口在被调用后立即返回,返回值代表了不同的含义。如在本例中,

  • recv() 返回值大于0,表示接受数据完毕,返回值即是接受到的字节数;

  • recv() 返回0,表示连接已经正常断开;

  • recv() 返回-1,且errno 等于EAGAIN,表示recv 操作还没执行完成;

  • recv() 返回-1,且errno 不等于EAGAIN,表示recv 操作遇到系统错误errno。

总结

网络服务端和客户端常用的Posix api;

服务端客户端
socket()socket()
bind()bind()可选
listen()connect()
accetp()
send()send()
recv()recv()

二. 修改句柄属性

2.1 fctl

fctl 函数作用:功能描述:根据文件描述词来操作文件的特性。

网络IO默认的连接是阻塞方式的,可以使用fcntl函数进行设置非阻塞模式。
函数原型:

#include<unistd.h>
#include<fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd ,struct flock* lock);
// 返回值:成功依赖cmd的值,失败返回-1;

fcntl()针对(文件)描述符提供控制.参数fd是被参数cmd操作(如下面的描述)的描述符.
针对cmd的值,fcntl能够接受第三个参数(arg)

fcntl函数有5种功能:

1.复制一个现有的描述符(cmd=F_DUPFD).
2.获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD).
3.获得/设置文件状态标记(cmd=F_GETFL或F_SETFL).
4.获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN).
5.获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW).

cmd参数说明:

参数 含义
F_GETFL 获取文件状态标志
F_SETFL 设置文件状态标志
F_GETFD 获取文件描述符标志
F_SETFD 设置文件描述符标志
F_GETLK 获取文件锁
F_SETLK 设置文件锁
F_DUPFD 复制文件描述符
F_GETOWN 取当前接受SIGIO和SIGURG信号的进程ID和进程组ID.正的arg指定一个进程ID,负的arg表示等于arg绝对值的一个进程中ID
F_SETOWN 设置当前接受SIGIO和SIGURG信号的进程ID和进程组ID.
状态标志:

标志 含义
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 为读、写打开
O_APPEND 每次写时追加
O_NONBLOCK 非阻塞模式
O_SYNC 等待写完成(数据和属性)
O_DSYNC 等待写完成(数据)
O_RSYNC 同步读、写
O_FSYNC 等待写完成(进FreeBSD和Mac OS X)
O_ASYNC 异步I/O(进FreeBSD和Mac OS X)

cmd 详解

F_DUPFD
返回一个如下描述的(文件)描述符:
1. 最小的大于或等于arg的一个可用的描述符与原始操作符一样的某对象的引用
2. 如果对象是文件(file)的话,返回一个新的描述符,这个描述符与arg共享相同的偏移量(offset)
3. 相同的访问模式(读,写或读/写)
4. 相同的文件状态标志(如:两个文件描述符共享相同的状态标志)
5. 与新的文件描述符结合在一起的close-on-exec标志被设置成交叉式访问execve(2)的系统调用

F_GETFD
取得与文件描述符fd联合close-on-exec标志,类似FD_CLOEXEC.如果返回值和FD_CLOEXEC进行与运算结果是0的话,文件保持交叉式访问exec(), 否则如果通过exec运行的话,文件将被关闭(arg被忽略)

F_SETFD 设置close-on-exec旗标。该旗标以参数arg的FD_CLOEXEC位决定。
F_GETFL 取得fd的文件状态标志,如同下面的描述一样(arg被忽略)
F_SETFL 设置给arg描述符状态标志,可以更改的几个标志是:O_APPEND, O_NONBLOCK,O_SYNC和O_ASYNC。
F_GETOWN 取得当前正在接收SIGIO或者SIGURG信号的进程id或进程组id,进程组id返回成负值(arg被忽略)
F_SETOWN 设置将接收SIGIO和SIGURG信号的进程id或进程组id,进程组id通过提供负值的arg来说明,否则,arg将被认为是进程id
O_NONBLOCK 非阻塞I/O;如果read(2)调用没有可读取的数据,或者如果write(2)操作将阻塞,read或write调用返回-1和EAGAIN错误
O_APPEND 强制每次写(write)操作都添加在文件大的末尾,相当于open(2)的O_APPEND标志
O_DIRECT 最小化或去掉reading和writing的缓存影响.系统将企图避免缓存你的读或写的数据. 如果不能够避免缓存,那么它将最小化已经被缓存了的数 据造成的影响.如果这个标志用的不够好,将大大的降低性能
O_ASYNC 当I/O可用的时候,允许SIGIO信号发送到进程组,例如:当有数据可以读的时候

注意
非阻塞要在accpt函数之前设置才能生效。
在修改文件描述符标志或文件状态标志时必须谨慎,先要取得现在的标志值,然后按照希望修改它,最后设置新标志值。不能只是执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位。

fcntl的返回值:
与命令有关。如果出错,所有命令都返回-1,
如果成功则返回某个其他值。下列三个命令有特定返回值:F_DUPFD,F_GETFD,F_GETFL以及F_GETOWN。第一个返回新的文件描述符,第二个返回相应标志,最后一个返回一个正的进程ID或负的进程组ID。

2.2 特殊作用

2.2.1 设置阻塞非阻塞

借助F_SETFD或F_SETFL命令实现对于fd 修改;

2.2.1 实例

/**********************使能非阻塞I/O********************/
int flags;
if(flags = fcntl(fd, F_GETFL, 0) < 0)
{
    perror("fcntl");
    return -1;
}
flags |= O_NONBLOCK;
if(fcntl(fd, F_SETFL, flags) < 0)
{
     perror("fcntl");
     return -1;
 }
/ *******************************************************/
 
 /**********************关闭非阻塞I/O******************/
 flags &= ~O_NONBLOCK;
 if(fcntl(fd, F_SETFL, flags) < 0)
 {
     perror("fcntl");
     return -1;
 }
/ *******************************************************/

2.2.2设置获取记录锁

结构体flock的指针:

struct flcok
{
   short int l_type; /* 锁定的状态*/
    //这三个参数用于分段对文件加锁,若对整个文件加锁,则:l_whence=SEEK_SET,l_start=0,l_len=0;

   short int l_whence;/*决定l_start位置*/
   off_t l_start; /*锁定区域的开头位置*/
   off_t l_len; /*锁定区域的大小*/
   pid_t l_pid; /*锁定动作的进程*/
};

l_type 有三种状态:

F_RDLCK 建立一个供读取用的锁定
F_WRLCK 建立一个供写入用的锁定
F_UNLCK 删除之前建立的锁定

l_whence 也有三种方式:

SEEK_SET 以文件开头为锁定的起始位置。
SEEK_CUR 以目前文件读写位置为锁定的起始位置
SEEK_END 以文件结尾为锁定的起始位置。

2.2.2 实例

 1 #include "filelock.h"
 2 
 3 /* 设置一把读锁 */
 4 int readLock(int fd, short start, short whence, short len) 
 5 {
 6     struct flock lock;
 7     lock.l_type = F_RDLCK;
 8     lock.l_start = start;
 9     lock.l_whence = whence;//SEEK_CUR,SEEK_SET,SEEK_END
10     lock.l_len = len;
11     lock.l_pid = getpid();
12 //  阻塞方式加锁
13     if(fcntl(fd, F_SETLKW, &lock) == 0)
14         return 1;
15     
16     return 0;
17 }
18 
19 /* 设置一把读锁 , 不等待 */
20 int readLocknw(int fd, short start, short whence, short len) 
21 {
22     struct flock lock;
23     lock.l_type = F_RDLCK;
24     lock.l_start = start;
25     lock.l_whence = whence;//SEEK_CUR,SEEK_SET,SEEK_END
26     lock.l_len = len;
27     lock.l_pid = getpid();
28 //  非阻塞方式加锁
29     if(fcntl(fd, F_SETLK, &lock) == 0)
30         return 1;
31     
32     return 0;
33 }
34 /* 设置一把写锁 */
35 int writeLock(int fd, short start, short whence, short len) 
36 {
37     struct flock lock;
38     lock.l_type = F_WRLCK;
39     lock.l_start = start;
40     lock.l_whence = whence;
41     lock.l_len = len;
42     lock.l_pid = getpid();
43 
44     //阻塞方式加锁
45     if(fcntl(fd, F_SETLKW, &lock) == 0)
46         return 1;
47     
48     return 0;
49 }
50 
51 /* 设置一把写锁 */
52 int writeLocknw(int fd, short start, short whence, short len) 
53 {
54     struct flock lock;
55     lock.l_type = F_WRLCK;
56     lock.l_start = start;
57     lock.l_whence = whence;
58     lock.l_len = len;
59     lock.l_pid = getpid();
60 
61     //非阻塞方式加锁
62     if(fcntl(fd, F_SETLK, &lock) == 0)
63         return 1;
64     
65     return 0;
66 }
67 
68 /* 解锁 */
69 int unlock(int fd, short start, short whence, short len) 
70 {
71     struct flock lock;
72     lock.l_type = F_UNLCK;
73     lock.l_start = start;
74     lock.l_whence = whence;
75     lock.l_len = len;
76     lock.l_pid = getpid();
77 
78     if(fcntl(fd, F_SETLKW, &lock) == 0)
79         return 1;
80 
81     return 0;
82 }

三、文件操作函数

3.1 相关接口函数

fwrite() 函数

用于将数据块按字节写入到文件中,返回实际成功写入的数据块个数。

size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);

参数说明:
ptr:指向要写入的数据块的指针。
size:每个数据块的字节数。
count:要写入的数据块个数。
stream:指向要写入的文件的指针。

使用 fwrite() 函数时,它会将 size 字节的数据块从 ptr 写入到指定的文件流 stream 中,并重复这个过程 count 次。

fread() 函数

用于从文件中按字节读取数据块,返回实际成功读取的数据块个数。

size_t fread(void *ptr, size_t size, size_t count, FILE *stream);

参数说明:
ptr:指向存储读取数据的内存块的指针。
size:每个数据块的字节数。
count:要读取的数据块个数。
stream:指向要读取的文件的指针。

使用 fread() 函数时,它会从指定的文件流 stream 中读取 size 字节的数据块,并重复这个过程 count 次,将读取的数据存储到 ptr 指向的内存块中。

fclose()函数

用于关闭打开的文件流,若成功关闭文件,则返回0;若关闭文件失败,则返回非零值。

int fclose(FILE *stream);

使用 fclose() 函数时,它会关闭指定的文件流,并刷新缓冲区中的数据。在关闭文件之前,它会将缓冲区中的数据写入到文件中。

fflush()函数

用于刷新输出缓冲区。若成功刷新缓冲区,则返回0;若刷新缓冲区失败,则返回非零值。

int fflush(FILE *stream);

参数说明:
stream:指向要刷新缓冲区的文件的指针。如果传入 NULL,则会刷新所有打开的文件流的缓冲区。

使用 fflush() 函数时,它会将输出缓冲区的内容立即写入到文件中(对于输出流)或者屏幕上(对于标准输出流 stdout)。这个函数通常用于确保数据被及时写入,而不是等到缓冲区满或者程序结束时才自动刷新。

fsync()函数

用于将文件数据同步到磁盘上的永久存储空间。若成功同步到磁盘,则返回0;若同步失败,则返回非零值。

int fsync(int fd);

参数说明:
fd:要同步到磁盘的文件描述符。

使用 fsync() 函数时,它会强制将文件缓冲区中的数据写入到磁盘上的永久存储空间。这个函数主要用于确保在系统崩溃或断电等异常情况下,文件数据不会丢失或损坏。
需要注意的是,fsync() 函数的调用可能会导致性能下降,因为它会强制进行磁盘写入操作。

setbuf()函数

用于在打开的文件上设置自定义的缓冲区。

void setbuf(FILE *stream, char *buffer);

参数说明:
stream:指向要设置缓冲区的文件的指针。
buffer:指向用于设置缓冲区的字符数组的指针。如果传入 NULL,则禁用缓冲区。

使用 setbuf() 函数时,它可以用于将自定义的字符数组作为缓冲区与文件关联。缓冲区提供了一种临时存储数据的方式,可以提高文件的读写性能。
需要注意的是,如果传入的 buffer 参数为 NULL,则会禁用缓冲区,即设置为无缓冲模式。在无缓冲模式下,每次写入或读取都会立即进行 I/O 操作,而不会暂存数据。这种模式适合于需要实时数据交换或者文件较小的情况。

write()函数

用于将数据写入文件或文件描述符的系统调用函数。成功时,返回写入的字节数。失败时,返回-1。

ssize_t write(int fd, const void *buf, size_t count);

参数说明:
fd:文件描述符,表示要写入的目标文件或设备。
buf:指向要写入数据的缓冲区的指针。
count:要写入的字节数。

write() 函数会尽可能将指定数量的字节从缓冲区 buf 写入到文件或设备中。它是一个阻塞函数,即在数据完全写入之前会一直等待。

fwrite 与 write 的区别

  • fwrite() 是库函数,默认使用缓冲区,即将数据先写入缓冲区,可以使用 setbuf() 或 setvbuf()
    函数自定义缓冲区。缓冲区可以提高写入效率,在遇到文件关闭、缓冲区满、调用 fflush() 等情况时会触发真正的写入操作,一次写盘
  • write() 函数 是系统调用,无缓冲的,数据直接写入到磁盘,涉及用户态和内核态的切换。

fwrite通过fflush(内部触发 write )把用户缓冲区数据刷新到内核缓冲区中,通过fsync把内核缓冲区数据刷新到磁盘。
在这里插入图片描述

参考

Linux协议栈posix接口浅析

本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以点击链接,详细查看详细的服务

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

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

相关文章

苹果恢复已删除的照片,3种超实用教程!

【大家帮帮孩子吧&#xff01;去旅游拍的写真不小心被我删掉了&#xff0c;回收站也找不到&#xff0c;有什么办法能恢复回来吗&#xff1f;】 不小心误删了重要照片该怎么办&#xff1f;大家都知道&#xff0c;苹果手机【最近删除】里的照片只能保留30天&#xff0c;超过了这…

CAD版本怎么在线转换?教你在线转换CAD版本方法

CAD文件版本转换通常是由于文件的创建者使用了与接收者不同的CAD软件版本。此外&#xff0c;如果接收者使用的CAD软件版本与创建者使用的版本不兼容&#xff0c;则可能需要进行文件版本转换&#xff0c;以便接收者能够正确地查看和编辑文件。很多小伙伴喜欢在线处理文件格式&am…

《零基础实践深度学习》(第2版)学习笔记,(五)深度学习与计算机视觉

文章目录 1. 计算机视觉概述2. 图像分类3. 目标检测 1. 计算机视觉概述 图像分类 目标检测 2. 图像分类 3. 目标检测

Guitar Pro8专业版吉他学习、绘谱、创作软件

Guitar Pro 8 专业版更强大&#xff01;更优雅&#xff01;更完美&#xff01;Guitar Pro 8.0 五年磨一剑&#xff01;多达30项功能优化&#xff01;Guitar Pro8 版本一共更新近30项功能&#xff0c;令吉他打谱更出色&#xff01;Guitar Pro8 是自2017年4月发布7.0之后发布的最…

独立游戏开发者的工具栈【Lumnis作者】

作为一名单人游戏开发者&#xff0c;需要成为多面手。 如果你想避免委托给承包商&#xff0c;需要身兼数职&#xff0c;并精通艺术、编程、游戏设计、音乐创作、营销等&#xff0c;具体取决于你制作的游戏。 学习所有这些需要时间和练习&#xff0c;但也需要金钱。 大多数游戏…

thread 的join方法

join方法的底层执行&#xff1f; 看如测试用例&#xff1a; -> 两个红色的框分别说明了sleep方法前后test01的状态&#xff0c;这个不是重点&#xff0c;只是一个验证而已。 重要的是test02的状态&#xff0c;调用join方法后&#xff0c;test02变成了WAITING状态&#xff…

每日一题 92反转链表||

题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a;…

冠达管理:股票成交量变小的含义?股价不涨是什么原因?

股票成交量是一个很重要的分析指标&#xff0c;遭到许多出资者的重视。那么股票成交量变小的意义&#xff1f;股价不涨是什么原因&#xff1f;冠达管理也为我们预备了相关内容&#xff0c;以供参考。 股票成交量变小的意义&#xff1f; 股票成交量是指在一定时间内&#xff0c…

2023 ChatGPT 3.5+4.0 + AI智能绘图-设计师专项源码 附安装教程

AI绘图专业设计 不得将程序用作任何违法违纪内容&#xff0c;不要让亲人两行泪 界面部分图解构&#xff1a; 前台show&#xff1a; 后台Show&#xff1a; 前端部署&#xff1a; 安装pm2管理器 点击设置 选择v16.19.1版本-切换版本 再新建一个网站 点击设置 添加反向代…

CSS变形与动画(一):transform变形 与 transition过渡动画 详解(用法 + 代码 + 例子 + 效果)

文章目录 变形与动画transform 变形translate 位移scale 缩放rotate 旋转skew 倾斜多种变形设置变形中心点 transition 过渡动画多种属性变化 变形与动画 transform 变形 包括&#xff1a;位移、旋转、缩放、倾斜。 下面的方法都是transform里的&#xff0c;记得加上。 展示效…

冠达管理:股票估值低为什么好于估值高?如何判断估值?

进行股票交易要掌握一些重要的相关常识&#xff0c;比如对股票估值状况的判别&#xff0c;假如出资者能清楚的得知买入的股票价格是否合适&#xff0c;那对于出资来说是大有益处的。但是&#xff0c;关于估值&#xff0c;会有估值低好于高一说&#xff0c;为什么估值低会好于估…

爬虫:Scrapy热门爬虫框架介绍

专栏介绍 结合自身经验和内部资料总结的Python教程&#xff0c;每天3-5章&#xff0c;最短1个月就能全方位的完成Python的学习并进行实战开发&#xff0c;学完了定能成为大佬&#xff01;加油吧&#xff01;卷起来&#xff01; 全部文章请访问专栏&#xff1a;《Python全栈教…

ROS之rviz显示GNSS/INS运动轨迹

目录 一、显示自定义圆形轨迹 二、显示GNSS/INS轨迹 2.1代码show_path.cpp 2.2CMakeLists.txt 2.3显示效果 一、显示自定义圆形轨迹 参考&#xff1a;&#xff08;九&#xff09;ROS在rviz中实时显示轨迹&#xff08;nav_msgs/Path消息的使用&#xff09;_nav_msgs/path.…

Java:正则表达式案例:爬数据,重复数据替换,数据分割

使用正则表达式查找一段文本中的内容 需求:请把下面文本中的电话&#xff0c;邮箱&#xff0c;座机号码&#xff0c;热线都爬取出来。 String data "电话:1866668888&#xff0c;18699997777\n" "或者联系邮箱: boniuitcast.cn&#xff0c;\n" "座机…

使用 PostgreSQL 创建全文搜索引擎1

PostgreSQL 提供了必要的模块&#xff0c;可以组合和创建自己的全文搜索搜索引擎。让我们尝试一下。 这是系列文章的第 1 部分&#xff0c;将要在其中探索 PostgreSQL 中的全文搜索功能&#xff0c;并研究我们可以完成多少典型的搜索引擎功能。在第 2 部分中&#xff0c;我们将…

【Redis从头学-0】一张思维导图对Redis做出基本介绍

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;Re…

[centos]设置主机名

1、设置 hostnamectl set-hostname 名字 2、查看是否生效 hostnamectl status 3、打开一个新链接就可以了

零代码编程:用ChatGPT批量删除Excel文件中的行

文件夹中有上百个Excel文件&#xff0c;每个文件中都有如下所示的两行&#xff0c;要进行批量删除。 在ChatGPT中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个处理Excel文件内容的任务&#xff0c;具体步骤如下&#xff1a; 打开F盘的文件夹&#x…

16.1.2 Linux 的多用户多任务环境

在 Linux 下面执行一个指令时&#xff0c;系统会将相关的权限、属性、程序码与数据等均载入内存&#xff0c; 并给予这个单元一个程序识别码 &#xff08;PID&#xff09;&#xff0c;最终该指令可以进行的任务则与这个 PID 的权限有关。根据这个说明&#xff0c;我们就可以简单…

ESD培训和咨询的相关服务

ESD&#xff08;Electrostatic Discharge&#xff0c;静电放电&#xff09;是指在两个物体之间发生的电荷平衡或不平衡&#xff0c;导致静电能量的释放。静电放电可能会对敏感的电子设备、芯片和电子元件产生损坏&#xff0c;因此对于需要处理电子设备的行业来说&#xff0c;ES…