linux系统编程-----下

news2024/12/25 9:38:12

linux网络编程

tcp通信

Berkeley Socket

TCP/IP协议族标准只规定了网络各个层次的设计和规范,具体实现则需要由各个操作系统厂商完成。最出名的网络库由BSD 4.2版本最先推出,所以称作伯克利套接字,这些API随后被移植到各大操作系统中,并成为了网络编程的事实标准。 socket 即套接字是指网络中一种用来建立连接、网络通信的设备,用户创建了 socket 之后,可以通过其发起或者接受 TCP 连接、可以向 TCP 的发送和接收缓冲区当中读写TCP数据段,或者发送 UDP 文本。

地址信息设置

**struct sockaddr 和 struct sockaddr_in
**
我们主要以IPv4为例介绍网络的地址结构。主要涉及的结构体有 struct in_addr 、 struct sockaddr 、 struct sockaddr_in 。其中 struct sockaddr 是一种通用的地址结构,它可以描述一个 IPv4或者IPv6的结构,所有涉及到地址的接口都使用了该类型的参数,但是过于通用的结果是直接用它 来描述一个具体的IP地址和端口号十分困难。

  struct sockaddr_in {
               sa_family_t    sin_family; /* address family: AF_INET */
               in_port_t      sin_port;   /* port in network byte order */
               struct in_addr sin_addr;   /* internet address */
           };

 /* Internet address. */
  struct in_addr {
               uint32_t       s_addr;     /* address in network byte order */
           };

大小端(Endianness :是指多个字节的数据在内存中的存储方式。在计算机系统中,一个多字节的数据类型会被分为若干个字节来存储,而这些字节的存放顺序就称为大小端。

大端法(Big-endian):是指数据的高位字节存储在内存的低地址处,而数据的低位字节存储在内存的高地址处。例如,在十六进制表示下,整数0x12345678在内存中的存储顺序为0x12 0x34 0x56 0x78。这种存储方式通常用于网络协议和一些处理器架构中,如Motorola 68000和IBM PowerPC等。

小端法(Little-endian):则是指数据的低位字节存储在内存的低地址处,而数据的高位字节存储在内存的高地址处。例如,在十六进制表示下,整数0x12345678在内存中的存储顺序为0x78 0x56 0x34 0x12。这种存储方式通常用于微处理器和操作系统中,如x86架构。

对于不同大小端的计算机之间进行数据交换时,需要进行大小端转换。具体来说,将一个多字节的数据类型拆分成单个字节后,按照相反的顺序重新组合即可完成大小端转换。

在C语言中,可以使用以下两个函数进行大小端转换操作:

  • htons()和htonl()函数:这两个函数可将16位或32位无符号整数从主机字节序转换为网络字节序,其中htons()用于转换16位整数,htonl()用于转换32位整数。如果本机字节序和网络字节序相同,则不会进行任何转换操作。

  • ntohs()和ntohl()函数:这两个函数可将16位或32位无符号整数从网络字节序转换为主机字节序,其中ntohs()用于转换16位整数,ntohl()用于转换32位整数。如果本机字节序和网络字节序相同,则不会进行任何转换操作。

需要注意的是,以上四个函数都需要包含头文件<arpa/inet.h>。此外,在其他编程语言中也有类似的函数可供使用。

域名和ip地址的对应关系

域名(Domain Name)和IP地址(Internet Protocol Address)之间存在一种对应关系,即每个域名都对应着一个或多个IP地址。

这种对应关系由DNS(Domain Name System)服务器来维护。当我们在浏览器中输入一个域名时,浏览器会向本地DNS服务器发送查询请求,请求该域名对应的IP地址。如果本地DNS服务器缓存了这个域名和其对应的IP地址,则直接返回该IP地址;否则,本地DNS服务器会向根DNS服务器发送查询请求,根DNS服务器会返回一个指向该域名所属顶级域名的权威DNS服务器的地址。接下来,本地DNS服务器再向该权威DNS服务器发送查询请求,获取该域名对应的IP地址,并将其缓存起来。最后,本地DNS服务器将该IP地址返回给浏览器,浏览器通过该IP地址访问目标网站。

举例来说,假设我们要访问网站www.example.com。首先,浏览器会向本地DNS服务器发送查询请求,请求该域名对应的IP地址。如果本地DNS服务器没有该域名的缓存记录,它会依次向根DNS服务器、com顶级域名的权威DNS服务器以及example.com域名的权威DNS服务器发送查询请求,最终获取到www.example.com对应的IP地址,并将其缓存起来。之后,本地DNS服务器将该IP地址返回给浏览器,浏览器通过该IP地址访问目标网站。

需要注意的是,一个域名可以对应多个IP地址,这些IP地址通常是为了实现负载均衡、故障转移等功能而提供的。此外,在特定情况下,一个IP地址也可以对应多个域名,例如,多个虚拟主机共用一台服务器的情况。

相关函数

#include <netdb.h>
struct hostent *gethostbyname(const char *name);
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
}

TCP通信

在这里插入图片描述

socket

Socket是一种在应用层和传输层之间的接口,可以用于实现不同机器或同一机器上的进程间通信。它是TCP/IP协议族中最基本的网络编程接口之一。

在Socket编程中,一个Socket通常由IP地址和端口号组成,用于标识网络上的一个进程。在客户端程序中,可以创建一个Socket并连接到服务器指定的IP地址和端口号上,从而与该服务器进行通信;在服务器程序中,可以创建一个Socket并绑定到指定的IP地址和端口号上,从而监听客户端连接请求并与其建立连接,以进行通信。

Socket可以使用不同的传输协议,如TCP(Transmission Control Protocol)和UDP(User Datagram Protocol),以实现可靠传输或非可靠传输。对于TCP协议,Socket提供面向连接的服务,数据传输之前需要先建立连接;对于UDP协议,Socket提供无连接的服务,数据传输时不需要事先建立连接。

Socket编程接口通常包含以下几个基本函数:socket()、bind()、listen()、accept()、connect()和send()/recv()等。其中,socket()用于创建Socket;bind()用于将Socket绑定到指定的IP地址和端口号上;listen()用于监听客户端连接请求;accept()用于接受客户端连接请求并建立连接;connect()用于建立与服务器的连接;send()/recv()用于发送和接收数据。

一般根据选择TCP或者UDP有着固定的写法。 socket 函数的返回值是一个非负整数

bind

bind()函数是一种可以在C语言中使用的方法,它可以用来创建一个新的函数,并将指定的this值和参数绑定到新的函数中。当新的函数被调用时,它会自动将这些绑定的值作为参数传递给原始函数。

connet

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

listen函数

listen()是一个网络编程中的函数,用于在服务器上等待客户端连接。当一个客户端请求与服务器建立连接时,服务器使用listen()函数开始监听传入的连接请求。一旦有连接请求到达,它们就被放置在一个队列中,直到服务器准备好接受这些连接并将它们分配给可用的线程或进程。

int listen(int sockfd, int backlog);

其中,sockfd 是套接字描述符,backlog 是等待连接队列的最大长度。

调用 listen 函数后,该套接字变成了被动套接字,可以接受来自客户端的连接请求。backlog 参数指定了等待连接队列的最大长度,如果有新的连接请求到达而等待队列已满,则客户端会收到拒绝连接的错误信息。

一般来说,backlog 的值应该设置为系统能够支持的最大值,以确保能够处理所有可能的连接请求。在 Linux 系统上,可以通过 cat /proc/sys/net/core/somaxconn 命令查看系统支持的最大队列长度,也可以使用 sysctl 命令来修改该值。

accept函数

accept() 是一个网络编程中的函数,用于接受客户端连接并返回与客户端通信的新 socket 对象和客户端地址。在服务器脚本中,我们使用 listen() 函数开始监听传入的连接请求,当有新的客户端连接请求到达时,accept() 函数会被调用以接受该连接。

accept 函数由服务端调用,用于从全连接队列中取出下一个已经完成的TCP连接。如果全连接队列为 空,那么 accept 会陷入阻塞。一旦全连接队列中到来新的连接,此时 accept 操作就会就绪,这种就绪 是读操作就绪,所以可以使用 select 函数的读集合进行监听。当 accept 执行完了之后,内核会创建一 个新的套接字文件对象,该文件对象关联的文件描述符是 accept 的返回值,文件对象当中最重要的结 构是一个发送缓冲区和接收缓冲区,可以用于服务端通过TCP连接发送和接收TCP段。

区分两个套接字是非常重要的。通过把旧的管理连接队列的套接字称作监听套接字,而新的用于发送和 接收TCP段的套接字称作已连接套接字。通常来说,监听套接字会一直存在,负责建立各个不同的TCP连 接(只要源IP、源端口、目的IP、目的端口四元组任意一个字段有区别,就是一个新的TCP连接),而某 一条单独的TCP连接则是由其对应的已连接套接字进行数据通信的。

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

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

sockfd: 必须,表示服务器的 socket 描述符,也就是要监听的套接字。

addr: 可选,表示客户端的地址信息,如果需要获取客户端的地址信息,则需要将这个参数传递给 accept() 函数。

addrlen: 必须,表示客户端地址结构体的长度,在调用 accept() 函数之前必须初始化为客户端地址结构体的大小。

当 accept() 函数成功时,会返回一个新的连接套接字(也就是通信套接字),可以通过这个新的套接字来进行后续的数据传输和通讯。如果 accept() 函数失败,则返回 -1,并设置相应的错误码,可以使用 strerror() 函数来获取对应的错误描述信息。

recv函数

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

其中,sockfd 是套接字描述符,buf 是一个指向缓冲区的指针,len 是缓冲区的最大长度(以字节为单位),flags 是操作标志位。

该函数返回接收到的字节数,如果出现错误,则返回 -1。可以通过 errno 全局变量获取详细的错误信息。

recv 函数会阻塞当前线程,直到有数据可读或者发生错误。如果在调用 recv 函数之前没有数据可读,那么它将一直阻塞,直到有数据到达为止。

buf 缓冲区用于存储接收到的数据,len 参数指定了缓冲区的大小,即最多能够接收到的数据量。如果实际接收到的数据超过了缓冲区大小,则多余的数据将被丢弃。

flags 参数可以用来指定一些操作标志位,比如是否启用 MSG_OOB(带外数据)模式、是否在接收时进行关闭操作等。

send函数

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

其中,sockfd 是套接字描述符,buf 是指向要发送数据的缓冲区的指针,len 是要发送的数据的长度(以字节为单位),flags 是操作标志位。

该函数返回已经成功发送的字节数,如果出现错误,则返回 -1。可以通过 errno 全局变量获取详细的错误信息。

buf 缓冲区用于存储要发送的数据,len 参数指定了需要发送的数据的长度。注意,在发送前应该确保缓冲区中的数据已经准备好,并且长度不超过缓冲区的大小。

flags 参数可以用来指定一些操作标志位,比如是否启动 MSG_OOB(带外数据)模式、是否在发送时进行关闭操作等。

send和recv函数

send() 和 recv() 函数是在网络编程中用于发送和接收数据的两个核心函数。这两个函数都是基于套接字(socket)实现的,因此只能用于网络通信。

send() 函数的格式如下:

send(socket, buffer, size, flags)

其中,

  • socket:指定要发送数据的套接字;
  • buffer:指定要发送的数据缓冲区;
  • size:指定要发送的数据长度;
  • flags:指定发送数据时的选项。

send() 函数的返回值为实际发送的数据量,如果出现错误,则返回 -1。

recv() 函数的格式如下:

recv(socket, buffer, size, flags)

其中,

  • socket:指定要接收数据的套接字;
  • buffer:指定用于接收数据的缓冲区;
  • size:指定缓冲区的大小;
  • flags:指定接收数据时的选项。

recv() 函数的返回值为实际接收到的数据量,如果出现错误,则返回 -1。

dos攻击

DOS(Denial of Service),即拒绝服务攻击,是一种通过向目标服务器发送大量请求来耗尽其资源以使其无法正常响应的攻击方式。

DOS 攻击可分为两类:

  1. 消耗计算资源的攻击。该类攻击通常会向目标服务器发送大量的请求,比如 SYN 请求洪水攻击、Ping 洪水攻击等,使其花费大量 CPU 和内存资源处理这些请求而无法正常工作。

  2. 消耗网络带宽的攻击。该类攻击通常会向目标服务器发送大量的数据包,比如 UDP 洪水攻击、ICMP 洪水攻击等,以消耗网络带宽并将目标服务器的网络连接拥堵,使其无法正常响应。

防范 DOS 攻击的措施主要包括以下几点:

  • 增加硬件设备的负载能力,比如增加带宽和存储容量等。

  • 防火墙和入侵检测系统等安全设备的配置和使用。

  • 在服务器端进行限制性访问,比如限制对某些关键资源的访问等。

  • 使用专门的软件和工具来监测网络流量和识别异常活动,及时发现并隔离攻击行为。

  • 增加访问控制的机制,比如限制某些 IP 地址的访问、设置访问频率限制等。

总之,防范 DOS 攻击需要综合考虑硬件设备的能力、网络安全设备的配置和使用、服务器端的安全设置以及对网络流量的监测和管理。

TIME_WAIT和setsockopt

如果是服务端主动调用 close 断开的连接,即服务端是四次挥手的主动关闭方,由之前的TCP状态转换图可知,主动关闭方在最后会处于一个固定2MSL时长的TIME_WAIT等待时间。在此状态期间,如果尝试使用 bind 系统调用对重复的地址进行绑定操作,那么会报错。

如果是服务端主动调用 close 断开的连接,即服务端是四次挥手的主动关闭方,由之前的TCP状态转换 图可知,主动关闭方在最后会处于一个固定2MSL时长的TIME_WAIT等待时间。在此状态期间,如果尝 试使用 bind 系统调用对重复的地址进行绑定操作,那么会报错。

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

setsockopt()函数

setsockopt()函数是用于设置套接字选项的系统调用。该函数可以用来设置一系列不同的选项,例如设置套接字的发送或接收缓冲区的大小、开启或关闭Nagle算法、设定超时时间等。

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

UDP通信

在这里插入图片描述

sendto和recvfrom函数

sendto()recvfrom()`是Linux系统中用于进行UDP套接字通信的函数,它们分别用于发送数据和接收数据。下面是这两个函数的简要说明:

  1. sendto()

    函数原型为ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)

    参数说明:

    • sockfd:需要发送数据的UDP套接字文件描述符。
    • buf:指向存放待发送数据的缓冲区。
    • len:待发送数据的长度。
    • flags:传输控制标志,一般设为0即可。
    • dest_addr:指向目的地址信息结构体的指针,包括目的IP地址和端口号等信息。
    • addrlen:指定dest_addr所指向的地址结构体的长度。

    返回值:

    • 成功:返回实际发送的字节数。
    • 失败:返回-1,并设置errno为相应的错误代码。
  2. recvfrom()

    函数原型为ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)

    参数说明:

    • sockfd:需要接收数据的UDP套接字文件描述符。
    • buf:指向存放接收数据的缓冲区。
    • len:缓冲区的长度。
    • flags:传输控制标志,一般设为0即可。
    • src_addr:指向发送方地址信息结构体的指针,包括发送方IP地址和端口号等信息。
    • addrlen:指向src_addr所指向的地址结构体的长度。

    返回值:

    • 成功:返回实际接收到的字节数。
    • 失败:返回-1,并设置errno为相应的错误代码。

使用UDP协议进行通信时,sendto()recvfrom()函数是常用的数据发送和接收函数,它们可以通过指定目的地址和源地址来实现点对点的通信。同时也可以通过设置传输控制标志等参数来控制数据传输的行为。

这两个函数的行为类似于 send 和 recv

epoll系统调用

epoll的基本原理:

和 select 一样, epoll 也是一种IO多路复用机制,它可以监听多个设备的就绪状态,让进程或者线程 只在有事件发生之后再执行真正的读写操作。 epoll 可以在内核态空间当中维持两个数据结构:监听事 件集合和就绪事件队列。监听事件集合用来存储所有需要关注的设备(即文件描述符)和对应操作(比 如读、写、挂起和异常等等),当监听的设备有事件产生时,比如网卡上接收到了数据并传输到了缓冲 区当中时,硬件会采用中断等方式通知操作系统,操作系统会将就绪事件拷贝到就绪事件队列中,并且 找到阻塞在 epoll_wait 的线程,让其就绪。监听事件集合通常是一个红黑树,就绪事件队列是一个线 性表。

和 select 相比, epoll 的优势如下:
除了水平触发,还支持边缘触发。

  • 监听事件集合容量很大,有多少内存就能放下多少文件描述符。
  • 监听事件集合常驻内核态,调用 epoll_wait 函数不会修改监听性质,不需要每次将集合从用户态 拷贝到内核态。
  • 监听事件和就绪事件的状态分为两个数据结构存储,当 epoll_wait 就绪之后,用户可以直接遍历 就绪事件队列,而不需要在所有事件当中进行轮询。

有了这些优势之后, epoll 逐渐取代了 select 的市场地位,尤其是在管理巨
大量连接的高并发场景 中, epoll 的性能要远超 select 。

使用epoll取代select

使用 epoll 主要有这样几个函数:

  • epoll_create 用于在内核之中创建一个 epoll 文件对象,这个文件对象中就包含之前所描述的监听事件集合和就绪设备集合。 epoll_create 的参数目前已经没有意义,填写一个大于0的数值即可。 epoll_create 的返回值是该文件对象对应的文件描述符。
  • epoll_ctl 用于调整监听事件集合。 op 的选项是 EPOLL_CTL_ADD 、 EPOLL_CTL_MOD 和EPOLL_CTL_DEL ,分别表示添加、修改和删除事件, event->events 用于描述事件的类型,其中EPOLLIN 表示读,EPOLLOUT 表示写。可以通过命令 man 7 socket 查看每个操作对应的事件类型如何。
  • epoll_wait 用于使线程陷入阻塞,直到监听的设备就绪或者超时。events 是一个传入传出参数,用于存储就绪设备队列, epoll_wait 的返回值就是就绪设备队列的长度,即就绪设备的个数。 timeout 描述超时时间,单位是毫秒,-1是永久等待。 maxevent 传入一个足够大的正数即可

使用epoll关闭长期不发消息的连接

和 select 一样, epoll 也可以监听已连接队列,判断 accept 是否就绪。配合上超时机制,可以用来实现自动断开功能:超过一段时间未发送消息的客户端的TCP连接会被服务端主动关闭。

epoll的边缘触发

epoll_wait 的就绪触发有两种方式:一种是默认的水平触发方式(Level-triggered),另一种是边缘触发 模式(Edge-triggered)。以读事件为例子:水平触发模式下,只要缓冲区当中存在数据,就可以使 epoll_wait 就绪;在边缘触发的情况下,如果缓冲区中存在数据,但是数据一直没有增多,那么 epoll_wait 就不会就绪,只有缓冲区的数据增多的时候,即下图中绿色的上升沿部分时,才能使 epoll_wait 就绪。
在这里插入图片描述
使用水平触发的话,线程能够以更短的响应时间来处理事件,但是这可能会导致饥饿问题,如果存在某 个事件传输的数据量过大,那么线程就会多次就绪直到处理完所有数据为止,而一些其他的任务所占用 的资源就会相对变少。使用边缘触发可以避免这个问题,为了确保读操作可以将所有数据读完,可以考 虑使用循环配合非阻塞的形式来处理。

在线程池架构中,主线程通常会将实际的IO交给子线程即工作线程完成,采用边缘触发可以有效地降低 主线程的响应频率,提高整体的性能。除此以外,如果一次请求对应一次响应是用户追求的通信模式, 那么边缘触发正好符合。

进程池和线程池

进程池的实现

我们以一个文件下载的应用为例子来介绍进程池结构:客户端可以向服务端建立连接,随后将服务端中存储的文件通过网络传输发送到客户端,其中一个服务端可以同时处理多个客户端连接的,彼此之间互不干扰。

零拷贝、sendfile和splice

目前我们传输文件的时候是采用 read 和 send 来组合完成,这种当中的数据流向是怎么样的呢?首先打开一个普通文件,数据会从磁盘通过DMA设备传输到内存,即文件对象当中的内核缓冲区部分,然后调用 read 数据会从内核缓冲区拷贝到一个用户态的buf上面(buf是 read 函数的参数),接下来调用send ,就将数据拷贝到了网络发送缓存区,最终实现了文件传输。

但是实际上这里涉及了大量的不必要的拷贝操作,比如下图中 read 和 send 的过程:
在这里插入图片描述

如何减少从内核文件缓冲区到用户态空间的拷贝呢?解决方案就是使用 mmap 系统调用直接建立文件和用户态空间buf的映射。这样的话数据就减少了一次拷贝。在非常多的场景下都会使用 mmap 来减少拷贝次数,典型的就是使用图形的应用去操作显卡设备的显存。除此以外,这种传输方式也可以减少由于系统调用导致的CPU用户态和内核态的切换次数。

在这里插入图片描述
使用 mmap 系统调用只能减少数据从磁盘文件的文件对象到用户态空间的拷贝,但是依然无法避免从用户态到内核已连接套接字的拷贝(因为网络设备文件对象不支持 mmap )。 sendfile 系统调用可以解决这个问题,它可以使数据直接在内核中传递而不需要经过用户态空间,调用 sendfile 系统调用可以直接将磁盘文件的文件对象的数据直接传递给已连接套接字文件对象,从而直接发送到网卡设备之上(在内核的底层实现中,实际上是让内核磁盘文件缓冲区和网络缓冲区对应同一片物理内存)。

在这里插入图片描述

#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

使用 sendfile 的时候要特别注意, out_fd 一般只能填写网络套接字的描述符,表示写入的文件描述符, in_fd 一般是一个磁盘文件,表示读取的文件描述符。从上述的需求可以得知, sendfile 只能用于发送文件方的零拷贝实现,无法用于接收方,并且发送文件的大小上限是2GB。

考虑到 sendfile 只能将数据从磁盘文件发送到网络设备中,那么接收方如何在避免使用 mmap 的情况下使用零拷贝技术呢?

一种方式就是采用管道配合 splice 的做法。 splice 系统调用可以直接将数据从内核管道文件缓冲区发送到另一个内核文件缓冲区,也可以反之,将一个内核文件缓冲区的数据直接发送到内核管道缓冲区中。所以只需要在内核创建一个匿名管道,这个管道用于本进程中,在磁盘文件和网络文件之间无拷贝地传递数据。

ssize_t splice(int fd_in, loff_t *off_in, int fd_out,loff_t *off_out, size_t len, unsigned int flags);

在这里插入图片描述

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

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

相关文章

Android Key Hash生成

在接入FaceBook 安卓第三方登录的时候&#xff0c;就需要获取Debug Android Hash Key。 Android Hah Key有两种&#xff0c;即开发密钥散列和发布密钥散列 获得散列值需要借助openssl工具。 下载并配置openssl 1、下载 到https://code.google.com/archive/p/openssl-for-win…

校验表格里的表单

<template><el-dialogtitle"收货地址":visible.sync"dialogFormVisible">{{ form }}<el-formref"form":model"form":rules"rules"label-width"100px"><el-form-itemlabel"活动名称&quo…

Roop:单图离线版软件包及使用方法!

你们要的“单图换脸”离线一键运行版来了。Roop发布几十个小时后&#xff0c;马不停蹄地搞了Colab在线版。其实这东西都挺好的&#xff0c;又快又方便&#xff0c;几乎没有任何硬件要求&#xff0c;点一点就可以搞定了。但是它有一个问题&#xff0c;就是没有“魔法” 就没法使…

国际电商网站APP开发-国际电商网站,跨境方案

跨境电商一种在国际贸易中进行电子商务的策略。它涉及到在线销售产品或服务给海外消费者&#xff0c;通常涉及到国际支付、物流和海外市场营销的问题。以下是一些跨境电商方案的例子&#xff1a; 跨境电商平台&#xff1a;建立自己的跨境电商平台&#xff0c;提供海外消费者便捷…

Docker安装达梦(DM)关系型数据库,DBeaver远程连接使用数据库

Docker安装达梦&#xff08;DM&#xff09;关系型数据库 首先你得去达梦数据库官网注册一个账号。 下载数据库部署包 官网&#xff1a;https://www.dameng.com/ 然后找到需要的数据库&#xff1a; 官网试用地址&#xff1a;https://eco.dameng.com/tour/?source_urlht…

ansible使用剧本操作硬盘

在一个节点添加一块20G的硬盘 通过ansible剧本判断是否存在第二块硬盘&#xff0c;且硬盘的大小大于10G 满足条件&#xff1a; 在此硬盘创建一个分区&#xff0c;大小为10G 使用此分区创建一个卷组 从此卷组中创建一个逻辑卷 将此逻辑卷格式化为xfs 将此逻辑卷挂载至/mountdir目…

上海28岁程序员失业,感叹:测试估计没戏了,想去卖点煎饼果子养家~

程序员危机&#xff0c;似乎是一个跨不过去的坎&#xff0c;最近&#xff0c;在职场论坛上看到了一位魔都程序员被裁的帖子&#xff0c;现在因为“互联网寒冬”不少程序员优化被裁。 帖子具体内容如下&#xff1a;因为疫情&#xff0c;老大哥所在部门被砍掉了&#xff0c;部门所…

科技项目验收测试报告获取有什么注意事项?作用都有哪些?

当科技项目通过测试并准备交付验收时&#xff0c;需要编写科技项目验收测试报告。科技项目验收测试报告是项目验收的重要部分&#xff0c;是对项目质量的一种客观证明。获取科技项目验收测试报告需要注意什么呢?本文从专业角度探讨这个话题&#xff0c;并介绍验收测试报告的作…

【数据分享】1929-2022年全球站点的逐日降水量(Shp\Excel\12000个站点)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;说到常用的降水数据&#xff0c;最详细的降水数据是具体到气象监测站点的降水数据&#xff01; 有关气象指标的监测站点数据&#xff0c;之前我们分享过1929-2022年全…

069:cesium围绕一个固定点自动左右旋转

第069个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置一个固定点为中心点,通过lookAtTransform来固化点,通过监听clock,来设置自动旋转。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共79行)相关…

网络安全怎么入行?有哪些误区需要避免?

目录 一、学习网络安全容易造成的误区 二、学习网络安全的基本准备与条件 三、网络安全学习路线 第一步&#xff1a;计算机基础 第二步&#xff1a;编程能力 第三步&#xff1a;安全初体验 第四步&#xff1a;分方向 怎么入门&#xff1f; 四、明确目标&#xff0c;定…

硬核科普:“画”说业界首个算网大脑

数字经济时代 算力已经成为核心生产力 中国移动提出“算力网络”全新理念 创新构建“连接算力能力” 新型信息服务体系 作为数字中国建设的国家队、主力军 中国移动布局算力网络的先锋队 移动云依托集团运营商禀赋优势 构建“4N31X”分布式云资源布局 为推动算力一点接入…

python 第四章 字符串str

系列文章目录 第一章 初识python 第二章 变量 第三章 基础语句 文章目录 4.1认识字符串字符串特征 4.2字符串输出4.3字符串输入4.4下标4.5切片4.6常用操作方法查找修改修改大小写转换字符串对齐删除空白字符判断 4.1认识字符串 字符串是 Python 中最常用的数据类型。我们一般使…

7min 到 40s:SpringBoot 优化居然可以玩出这么多花样

背景 耗时问题排查 观察 SpringBoot 启动 run 方法 监控 Bean 注入耗时 优化方案 如何解决扫描路径过多&#xff1f; 如何解决 Bean 初始化高耗时&#xff1f; 新的问题 SpringBoot 自动化装配&#xff0c;让人防不胜防 使用 starter 机制&#xff0c;开箱即用 背景 公…

我的GIT练习TWO

目录 前言 GIT安装教程 Git作者 GIT优点 GIT缺点 为什么要使用 Git GIT练习TWO ​编辑 总结 前言 Git 是一个分布式版本控制及源代码管理工具;Git 可以为你的项目保存若干快照&#xff0c;以此来对整个项目进行版本管理 GIT安装教程 点击进入查看教程&#xff1a;点击进入…

怎么清除电脑缓存?

由于我们电脑的硬盘内部的很多数据的传输速度和外界介面的传输速度不同&#xff0c;这时就有一个所谓的缓存来给我们把这些数据传输速度不同的差异更好的缓冲了一下&#xff0c;也正是因为这个原因我们的电脑才能够运行的更加流畅&#xff0c;感觉不到卡顿。 电脑在使用的过程…

C++算法:有向无环图实现游戏技能树

文章目录 前言一、游戏技能树的逻辑二、实现代码1、建立图2、各种方法函数&#xff08;1&#xff09;、出度入度表生成方法&#xff08;2&#xff09;、读取技能点&#xff08;3&#xff09;、修改技能点&#xff08;4&#xff09;、拓扑排序 3、测试代码 总结 前言 前面文章图…

【Vue】三:Vue组件:props配置 父组件获取子组件

文章目录 1.props配置1.1 方式一&#xff1a;简单的接收方式&#xff1a;直接采用数组接收1.2 方式二&#xff1a;添加类型限制1.3 方法三&#xff1a;添加类型限制&#xff0c;添加默认值&#xff0c;添加必要性1.4 不要修改props中的值 2.从父组件获取子组件 1.props配置 父…

Vulkan Tutorial 0 引言

1 开发环境 在这一章中&#xff0c;我们将设置您开发Vulkan应用程序的环境&#xff0c;并安装一些有用的库。除了编译器之外&#xff0c;我们将使用的所有工具都与Windows、Linux和MacOS兼容&#xff0c;但安装它们的步骤有些不同&#xff0c;这就是为什么它们在这里被单独描述…

MySQL所有基本操作详解

一.MySQL的基本操作 首先sql操作中的关键字的是大小写不敏感的&#xff0c;create 和CREATE是一样的。 1.库操作 1. 1查看数据库 show databases;show 和databases 之间有一个或者多个空格注意是databases而不是database结尾分号是英文形式&#xff0c;分号在SQL中是表示一…