网络基础-PosixAPI

文章目录

  • 一.网络常用接口
    • 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课程感兴趣的读者,可以点击链接,详细查看详细的服务

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

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

相关文章

数据库操作不再困难,MyBatis动态Sql标签解析

系列文章目录 MyBatis缓存原理 Mybatis的CachingExecutor与二级缓存 Mybatis plugin 的使用及原理 MyBatis四大组件Executor、StatementHandler、ParameterHandler、ResultSetHandler 详解 MyBatisSpringboot 启动到SQL执行全流程 数据库操作不再困难&#xff0c;MyBatis动态S…

n-皇后问题

希望这篇题解对你有用&#xff0c;麻烦动动手指点个赞或关注&#xff0c;感谢您的关注 不清楚蓝桥杯考什么的点点下方&#x1f447; 考点秘籍 想背纯享模版的伙伴们点点下方&#x1f447; 蓝桥杯省一你一定不能错过的模板大全(第一期) 蓝桥杯省一你一定不能错过的模板大全…

Python教程(8)——一文弄懂Python字符串操作(下)

Python字符串操作 字符串常用方法字符串更多方法介绍 字符串常用方法 字符串在编程中是一种不可或缺的数据类型&#xff0c;它在文本和字符数据时提供了丰富而强大的功能。掌握了字符串的使用方法&#xff0c;你能够更加便捷地进行文本处理、数据操作、用户交互等任务&#xf…

opencv图片换背景色

#include <iostream> #include<opencv2/opencv.hpp> //引入头文件using namespace cv; //命名空间 using namespace std;//opencv这个机器视觉库&#xff0c;它提供了很多功能&#xff0c;都是以函数的形式提供给我们 //我们只需要会调用函数即可in…

文献阅读:AnnoLLM: Making Large Language Models to Be Better Crowdsourced Annotators

文献阅读&#xff1a;AnnoLLM: Making Large Language Models to Be Better Crowdsourced Annotators 1. 文章简介2. 方法介绍3. 实验考察 1. 实验结果2. 消解实验3. Consistency & Stability 4. 结论 & 思考 文献链接&#xff1a;https://arxiv.org/abs/2303.16854 …

GrapeCity Documents for Excel, Java Edition Crack

GrapeCity Documents for Excel, Java Edition Crack 增加了对SpreadJS.sjs文件格式的支持&#xff1a; 更快地将大型Microsoft Excel文件转换为.sjs格式。 使用较小的占用空间保存导出的文件。 将Excel/SpreadJS功能导入SpreadJS/从SpreadJS导出。 从.sjs文件中压缩的JSON文件…

@Param详解

文章目录 背景什么是ParamParam的使用方法使用方法&#xff1a;遇到的问题及因Param解决了什么问题使用与不使用对比 Param是如何进行映射的总结 背景 最近在开发过程中&#xff0c;在写mapper接口是在参数前加了Param注解&#xff0c;但是在运行的时候就会报错&#xff0c;说…

设备取电芯片LDR6328Q

2021年5月&#xff0c;USB-IF 协会发布了全新的USB PD3.1规范&#xff0c;该规范将快充功率上限从100 W提升至240W&#xff08;支持Extended Power Range&#xff0c;简称EPR&#xff09;。充电功率的提升也让USB PD的应用从手机、笔记本电脑&#xff0c;扩展到便携式设备、物联…

教育行业文件协作的最佳实践分享!

在教育工作中&#xff0c;经常需要进行文件协作&#xff0c;无论是师生间还是老师与老师之间。目前最常用的文件协作方式就是通过社交工具或者邮件进行文件共享。 这种协作方式的缺点 1、大文件传输不便&#xff1a;这种协作方式依托于社交工具&#xff0c;对于大文件传输并不…

百日筑基篇——python爬虫学习(一)

百日筑基篇——python爬虫学习&#xff08;一&#xff09; 文章目录 前言一、python爬虫介绍二、URL管理器三、所需基础模块的介绍1. requests2. BeautifulSoup1. HTML介绍2. 网页解析器 四、实操1. 代码展示2. 代码解释1. 将大文件划分为小的文件2. 获得结果页面的url3. 获取结…

opsForHash() 与 opsForValue 请问有什么区别?

&#x1f449;&#xff1a;&#x1f517;官方API参考手册 如图&#xff0c;opsForHash()返回HashOperations<K,HK,HV>但是 opsForValue()返回ValueOperations<K,V>… 区别就是opsForHash的返回值泛型中有K,HK,HV,其中K是Redis指定的某个数据库里面某一个关键字(由…

Flutter BottomSheet 三段式拖拽

BottomSheetBehavior 追踪 BottomSheet系统默认实现效果准备要实现的功能点&#xff1a;定义三段式状态&#xff1a;BottomSheetBehavoir阀值定义1. 未达到滚动阀值&#xff0c;恢复状态2. 达到滚动阀值&#xff0c;更新状态 前面倒是有讲过Android原生的BottomSheetBehavior&a…

谈谈我的感受

虽然清楚知识需要靠时间沉淀&#xff0c;但在看到自己做不出来的题别人会做&#xff0c;自己写不出的代码别人会写时还是会感到焦虑怎么办&#xff1f; 感受 当我们比别人弱的时候&#xff0c;可能会感到挫败、失落、沮丧或无力。这种感受往往是因为我们与自己设定的标准或别人…

时序预测-Informer简介

Informer介绍 1. Transformer存在的问题 Informer实质是在Transformer的基础上进行改进&#xff0c;通过修改transformer的结构&#xff0c;提高transformer的速度。那么Transformer有什么样的缺点&#xff1a; &#xff08;1&#xff09;self-attention的平方复杂度。self-…

ruoyi-cloud微服务新建子模块

目录 相关文章1、复制system模块2、在modules下的 pom.xml文件中添加子模块 test3、进入 test模块修改 pom.xml4、修改对应的包名、目录名和启动应用程序为test5、修改bootstrap.yml文件中的端口号和应用名称6、nacos中克隆 system-dev.yml的配置&#xff0c;修改名称为 test-d…

章节7:XSS检测和利用

章节7&#xff1a;XSS检测和利用 测试payload <script>alert(XSS)</script> <script>alert(document.cookie)</script> ><script>alert(document.cookie)</script> ><script>alert(document.cookie)</script> &qu…

React Native 图片组件基础知识

在 React Native 中使用图片其实跟 HTML 中使用图片一样简单&#xff0c;在 React Native 中我们使用Image组件来呈现图片的内容&#xff0c;其中主要的属性有&#xff1a;source。这个属性主要是设置图片的内容&#xff0c;它可以是网络图像地址、静态资源、临时本地图像以及本…

Java地图专题课 基本API BMapGLLib 地图找房案例 MongoDB

本课程基于百度地图技术&#xff0c;由基础入门开始到应用实战&#xff0c;适合零基础入门学习。将企业项目中地图相关常见应用场景的落地实战&#xff0c;包括有地图找房、轻骑小程序、金运物流等。同时讲了基于Netty实现高性能的web服务&#xff0c;来处理高并发的问题。还讲…

ElasticSearch单节点部署

&#x1f388; 作者&#xff1a;互联网-小啊宇 &#x1f388; 简介&#xff1a; CSDN 运维领域创作者、阿里云专家博主。目前从事 Kubernetes运维相关工作&#xff0c;擅长Linux系统运维、开源监控软件维护、Kubernetes容器技术、CI/CD持续集成、自动化运维、开源软件部署维护…

差分升级在物联网水表上的实现与应用(学习)

摘要 当越来越多的物联网水表加入抄表系统后&#xff0c;实现了水表数据的信息化&#xff0c;并且当水表终端需要技术更新时&#xff0c;通过网络方式来升级产品可以高效修复设备面临的问题&#xff0c;减少用户损失&#xff0c;降低维护成本&#xff0c;但同时也对有限的网络…