C++跨平台socket编程

C++跨平台socket编程

  • 一、概述
    • 1.1 TCP协议
      • 1.1 TCP 的主要特性
      • 1.2 TCP报文格式
    • UDP报文格式
    • IP协议
    • 使用windows编辑工具直接编辑Linux上代码
  • 二、系统socket库
    • 1.windows上加载socket库
    • 2.创建socket
      • 2.1 windows下
      • 2.2 linux下
    • 3.网络字节序
    • 4.bind端口
    • 5.listen监听并设置最大连接数
    • 6.accept读取用户连接信息
    • 7.服务器通过recv接收客户端发送信息
      • 服务器循环接收客户端数据
    • 8.服务器send回应客户端数据
    • 9.服务器开启多线程并发处理客户端连接
      • 9.1 windows下
      • 9.2 linux下
  • 三、封装跨平台XTcp类
    • 1.windows下测试
    • 2.linux下测试
    • 3.创建并测试XTcp的dll动态链接库
      • 3.1 创建
      • 3.2 测试
    • 4.创建并测试XTcp的so动态链接库
      • 4.1 创建
      • 4.2 测试
  • 四、TcpClient编写与tcp编程总结
    • 1.connect与三次握手的过程
      • 1.1 为什么需要三次握手?
    • 2 connect客户端连接服务器
    • 3.tcp编程总结
  • 五、高并发服务器开发和测试
    • 1.Windows中设置socket阻塞和非阻塞
    • 2.Linux中设置socket阻塞和非阻塞
    • 3.通过select实现connect的超时处理
      • 为什么使用select实现connect的超时处理?
    • 4.并发测试工具ab
    • 5.基于epoll的高性能服务器
      • 注意
    • 6.epoll、select 和阻塞 accept 之间的关系
      • 1.监听套接字队列
      • 2.**accept 函数**
      • 3.I/O 多路复用机制
  • 六、http协议
    • 请求
      • 2.**accept 函数**
      • 3.I/O 多路复用机制
  • 六、http协议
    • 请求

一、概述

image-20240613090208126

1.1 TCP协议

TCP协议提供可靠、有序、且无差错的数据传输服务。

1.1 TCP 的主要特性

面向连接

  • 在传输数据之前,TCP 需要在通信双方之间建立一个连接,这个过程称为三次握手(Three-way Handshake)。

可靠传输

  • TCP 通过确认(ACK)、序列号、超时重传等机制保证数据的可靠传输。

有序传输

  • TCP 确保数据按序到达目标,即使数据包乱序到达,TCP 也会重新排序。

流量控制

  • TCP 使用滑动窗口机制来控制数据流量,避免发送方发送数据过快,超过接收方的处理能力。

拥塞控制

  • TCP 有内置的拥塞控制算法,通过调整发送速率避免网络拥塞。

1.2 TCP报文格式

image-20240613090623626

image-20240613090657390

image-20240613090713341

image-20240613090855493

image-20240613091114833

UDP报文格式

image-20240613091800963

image-20240613091815421

image-20240613091906618

image-20240613092003392

IP协议

image-20240613095801498

image-20240613095904615

image-20240613100200476

image-20240613100319161

image-20240613101134185

image-20240613101444935

image-20240613102411601

使用windows编辑工具直接编辑Linux上代码

ubuntu: apt-get install samba

centos7:sudo yum install samba samba-client samba-common -y

配置环境:

vim ../etc/samba/smb.conf

文件末尾加入共享目录:

image-20240613112503982

重启一下服务:

image-20240613112541070

在根目录下创建code目录:

image-20240613112626849

设置权限:

image-20240613113536311

添加Samba用户,设置密码:

image-20240613114027279

检查服务是否都启动了(ubuntu跳过):

image-20240613114111312

如果服务没有启动(centos):

sudo systemctl enable smb nmb
sudo systemctl start  smb nmb

如果服务没有启动(ubuntu):

sudo service smbd restart

在windows系统中连接共享目录:

image-20240613114126145

image-20240613114131475

image-20240613114204383

image-20240613114308287

如果再次连接samba,并尝试进入共享文件夹,出现报错你没有权限访问,可能是防火墙问题,输入命令:

image-20240614090951999

sudo setenforce 0

sudo iptables -F

二、系统socket库

套接字(Socket)是网络编程中用于在计算机之间进行通信的端点。它提供了一种进程间通信的机制,可以在同一台计算机上或不同计算机之间进行数据交换。套接字的概念和实现是网络通信的重要基础。

套接字是一个主机本地应用程序创建的,被操作系统所控制的接口(“门”)。

应用程序通过这个接口,使用传输层提供的服务,跨网络发送(接收)消息到(从)其他应用进程。

C/S模式的通信接口——套接字接口。

1.windows上加载socket库

在Windows中,Winsock库不是自动加载的。在使用网络功能之前,程序必须显式地初始化Winsock库,以便系统可以分配资源并为网络通信做好准备。初始化之后,程序就可以创建套接字并使用网络功能了。

image-20240613132121538

每次编写涉及套接字编程的应用程序时,都需要在程序的开头部分添加这两行代码,并在程序结束时调用 WSACleanup() 来清理资源。

2.创建socket

2.1 windows下

image-20240613133102728

socket(AF_INET, SOCK_STREAM, 0):创建一个套接字。

AF_INET 指定使用IPv4地址族,SOCK_STREAM 指定使用流式套接字(TCP),0 表示使用默认的协议(对于 SOCK_STREAM 即TCP协议)。socket 函数成功时返回一个非负整数表示创建的套接字,失败时返回 -1

2.2 linux下

因为Linux下各种库和windows不一样,个别函数也不一样,因此使用条件编译的方法。

image-20240613141234085

image-20240613141241423

image-20240613141319406

我们一次性创建两千个socket。

在windows下,可以正常创建。

image-20240613142043791

在Linux下,因为系统默认一个进程最多创建1024个socket,因此1024之后的创建不了。

image-20240613142206232

我们可以通过ulimit -n修改最大可创建socket个数。

此时再运行就可以了。

image-20240613142305788

3.网络字节序

网络字节序(Network Byte Order)是指在网络传输中,数据的字节排列顺序。它采用的是大端字节序(Big-Endian),即最高有效字节(Most Significant Byte,MSB)在前,最低有效字节(Least Significant Byte,LSB)在后。

image-20240613145510909

在这里插入图片描述

#include <arpa/inet.h>

//将主机字节序转换为网络字节序
 unit32_t htonl (unit32_t hostlong);
 unit16_t htons (unit16_t hostshort);
 //将网络字节序转换为主机字节序
 unit32_t ntohl (unit32_t netlong);
 unit16_t ntohs (unit16_t netshort);

4.bind端口

获取端口号

image-20240613150623865

配置地址结构

image-20240613150655433

绑定端口

image-20240613151309287

image-20240613151254967

image-20240613151321306

在Linux中编译发现报错,说明有头文件不一致。
image-20240613151408675

image-20240613151427482

image-20240613151440546

image-20240613151638056

image-20240613151722048

image-20240613151714876

5.listen监听并设置最大连接数

int listen(int sockfd, int backlog);

参数说明

  • sockfd:这是一个已经通过socketbind函数创建并绑定到特定地址和端口的套接字描述符。
  • backlog:指定等待连接队列的最大长度,即在accept函数被调用之前,可以有多少个连接请求处于等待状态。

当一个服务器套接字处于监听状态时,它会创建一个队列来存储那些尚未被服务器接受(accept)的传入连接请求。当完全连接队列已满且有新的连接到达时,新连接可能会被拒绝(客户端将收到一个错误)。这个队列实际上包含两个部分:

  • 半连接队列:存放已经完成三次握手中的第一步(SYN)但尚未完成整个握手过程的连接请求。

  • 完全连接队列:存放已经完成三次握手的连接请求,等待应用程序调用 accept

在实际应用中,backlog 的值会影响服务器在高并发环境下的表现。设置过低的 backlog 值可能导致拒绝合法的连接请求,而设置过高的值可能会消耗更多的系统资源。

image-20240613153606265

6.accept读取用户连接信息

accept 函数是套接字编程中用于从监听队列中提取第一个连接请求的系统调用。它会创建一个新的套接字用于与客户端进行通信。accept 函数通常与服务器端的监听套接字配合使用,在客户端发起连接请求并经过 listen 函数处理后,由 accept 函数接受该请求。

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

参数说明

  • sockfd:已绑定到本地地址并处于监听状态的套接字描述符。
  • addr:指向 sockaddr 结构体的指针,用于存储客户端的地址信息。可以是 NULL
  • addrlen:指向一个 socklen_t 变量的指针,用于存储 addr 结构体的大小。调用前应设置为 addr 结构体的大小,调用后包含实际的地址长度。可以是 NULL

返回值

  • 成功:
    • accept 函数成功时返回一个新的套接字描述符,这个新的套接字用于与客户端进行通信。
    • 返回值是一个非负整数,表示新的连接套接字。
  • 失败:
    • accept 函数失败时返回 -1,并设置 errno 以指示错误类型。

image-20240613161329417

image-20240613161907894

image-20240613161856217

7.服务器通过recv接收客户端发送信息

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

参数说明

  • sockfd:一个已经连接的套接字描述符。
  • buf:指向用于存放接收到的数据的缓冲区。
  • len:缓冲区的长度,即可以接收的数据的最大字节数
  • flags:接收操作的标志,可以是0或以下值的组合:
    • MSG_OOB:接收带外数据。
    • MSG_PEEK:窥视操作,将数据复制到缓冲区但不从输入队列中删除。
    • MSG_WAITALL:等待完整的数据,直到缓冲区满或发生错误。
    • MSG_DONTWAIT:非阻塞操作,如果没有数据可读,立即返回。

image-20240613163439267

image-20240613163516966

服务器循环接收客户端数据

image-20240613165850994

image-20240613165709525

不过现在有一个新的问题,如果有第二个、第三个…多个客户端连接,只有当第一个客户端退出,服务器才能收到其他客户端的消息,这是因为我们是在单线程中处理消息。

8.服务器send回应客户端数据

image-20240614094115205

image-20240614094238801

9.服务器开启多线程并发处理客户端连接

image-20240614094858199

image-20240614094922904

9.1 windows下

image-20240614094823358

9.2 linux下

image-20240614100011903

image-20240614095954386

三、封装跨平台XTcp类

为什么需要XTcp类?

与系统相关的头文件、socket的初始化、绑定等函数容易出错,同时写起来很麻烦,因此包装成一个类,直接调用类的方法。

image-20240614102940041

image-20240614103013506

image-20240614142423415

  • 构造函数
    • image-20240614142500436
  • 创建和关闭socket
    • image-20240614142513832
    • 关于为什么提供CloseSocket而不是直接析构中调用closesocket?
      • image-20240614143446275
      • 析构中调用WSACleanup()同理,目前先不做析构。
  • 绑定与监听
    • image-20240614142531557
  • 接收客户端连接
    • image-20240614142557319
  • 发送、接收数据
    • image-20240614142613638
  • main 和 Tcpserver
    • image-20240614142758820
    • image-20240614142903928

1.windows下测试

image-20240614143612055

2.linux下测试

image-20240614143919626

image-20240614144132686

3.创建并测试XTcp的dll动态链接库

3.1 创建

image-20240614145600444

image-20240614145723975

image-20240614145949052

注意,在Windows系统上,套接字编程需要链接 Ws2_32.lib 库。确保在项目设置中包含这个库。
image-20240614150730908

image-20240614151632011

image-20240614151637950

image-20240614151758866

image-20240614151850867

如果程序需要执行,则要配置工作目录为dll所在目录。

image-20240614151939723

image-20240614152000819

image-20240614152006743

3.2 测试

image-20240614153014783

image-20240614153039050

image-20240614153106262

image-20240614153152787

image-20240614153518313

4.创建并测试XTcp的so动态链接库

4.1 创建

image-20240614154413141

运行makefile会发现有报错,windows的导出宏在linux没有,还有头文件只能包含一次也没有。
image-20240614154528775

image-20240614154844373

image-20240614154907370

4.2 测试

image-20240614155003044

再把测试程序也编译一下。

image-20240614155910293

image-20240614155919032

根据提示修改makefile文件

image-20240614160025436

image-20240614160040524

image-20240614160455057

image-20240614160535892

在Linux中,运行程序时确实需要确保动态库的路径在系统的库搜索路径中,否则程序将无法找到并加载所需的动态库。

image-20240614160630703

image-20240614160814607

四、TcpClient编写与tcp编程总结

1.connect与三次握手的过程

image-20240614165430057

1.1 为什么需要三次握手?

确保双方都有能力发送和接收数据:通过三次握手,客户端和服务器可以确认双方都能够发送和接收数据包。

同步初始序列号:三次握手的过程还可以确保双方同步初始序列号,以防止因网络传输延迟或重传而导致的数据包混乱。

防止旧的重复连接初始化:三次握手可以防止旧的、重复的连接请求在网络中滞留并意外创建连接。

如果只进行两次,客户端收到服务器发送的ack后,知道服务器能收到客户端消息,所以客户端能保证服务器收到正确数据。但是如果客户端不回复服务器这一次的syn,那么服务器不知道客户端能否正确收到服务器的消息。

2 connect客户端连接服务器

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

参数说明:

  • sockfd:由socket函数返回的套接字文件描述符。它标识一个套接字。
  • addr:指向struct sockaddr类型的指针,包含了要连接的服务器的IP地址和端口号。
  • addrlen:结构体sockaddr的长度。

返回值:

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

image-20240618192407353

image-20240618192425373

image-20240618192441366

image-20240618192648879

3.tcp编程总结

image-20240618192747991

五、高并发服务器开发和测试

1.Windows中设置socket阻塞和非阻塞

阻塞模式:

  • 套接字在创建时默认是阻塞模式。
  • 调用套接字函数(如 acceptconnectrecvsend 等)时,如果操作无法立即完成,函数会阻塞(即挂起执行)直到操作完成或发生错误。

非阻塞模式:

  • 调用套接字函数时,如果操作无法立即完成,函数立即返回一个错误(如 EWOULDBLOCK),而不是阻塞等待。
  • 程序通常需要轮询套接字状态或使用事件驱动机制(如 selectpollepoll)时使用非阻塞模式。

我们的目的是:在建立连接的时候是非阻塞模式,在接收数据的时候是阻塞模式,因为接收数据我们是多线程方式,所以设置为阻塞不影响别的线程运行。

ioctlsocket 是 Windows 操作系统中用于控制套接字行为的函数。

int ioctlsocket(
  SOCKET s,
  long cmd,
  u_long *argp
);

参数说明:

  • s: 套接字的描述符。
  • cmd: 控制命令,指定要执行的操作。
  • argp: 命令参数,根据 cmd 指定不同的含义。

FIONBIO: 设置或清除非阻塞模式。

  • 如果 *argp 为非零值,则套接字设置为非阻塞模式。
  • 如果 *argp 为零,则套接字设置为阻塞模式。

返回值:

  • 如果函数成功,返回 0。

image-20240618194404408

2.Linux中设置socket阻塞和非阻塞

image-20240618194912296

image-20240618194929822

image-20240618200049033

3.通过select实现connect的超时处理

为什么使用select实现connect的超时处理?

  1. 阻塞 connect 无法设置超时
    • connect 是一个阻塞操作,当服务器不可达时,可能会阻塞很长时间。这会导致程序响应变慢,尤其是在高并发环境下。
  2. 非阻塞 connect
    • 通过将套接字设置为非阻塞模式,connect 会立即返回并设置 errnoEINPROGRESS,表示连接正在进行中。此时,程序不会被阻塞,可以继续处理其他任务。

在非阻塞模式下使用 select 实现 connect 的超时处理是一个常见的做法,因为直接使用阻塞的 connect 函数无法设置超时。

select是一个用于多路复用的系统调用,用来监视多个文件描述符,等待其中的一个或多个文件描述符变为"就绪"状态,也就是可以进行I/O操作(如读或写)而不会阻塞。

在 select 函数中,有三个文件描述符集合用于监听不同类型的事件:

  1. 读集合(readfds):用于监听可读事件。读事件是指文件描述符上有数据可以读取,或者连接已经关闭,或有一个新的连接请求(对于监听套接字)。当某个文件描述符触发读事件时,select会在 readfds 集合中设置该文件描述符。
  2. 写集合(writefds):用于监听可写事件。写事件是指文件描述符可以执行写操作而不会阻塞。通常在以下情况下触发写事件:当套接字的发送缓冲区有空间时,select会在 writefds 集合中设置该文件描述符。
  3. 异常集合(exceptfds):用于监听异常事件。

文件描述符集合:

select 中,文件描述符集合使用 fd_set 结构。可以通过以下宏来操作文件描述符集合:

  • FD_ZERO(fd_set *set):清空集合。
  • FD_SET(int fd, fd_set *set):将文件描述符加入集合。
  • FD_CLR(int fd, fd_set *set):将文件描述符从集合中删除。
  • FD_ISSET(int fd, fd_set *set):检查文件描述符是否在集合中。

我们可以将需要监听的套接字放入套接字文件描述符集合,由该集合负责帮我们监听该文件描述符表中这些套接字文件描述符对应的套接字的缓冲区中是否有数据需要处理。

这个监听集合的大小为1024(默认最大值),但需要注意的是,虽然这个集合的大小为1024,但实际能帮我们监听的客户端套接字只有1020个,因为前1-3个分别用于监听标准输入、标准输出和标准出错,第四个用于存放服务器套接字。通过这个监听集合,我们就可以实现对多个socket的同时监听。

在非阻塞模式下调用 connect 函数时,它不会阻塞等待连接完成,而是立即返回。如果连接不能立即完成,errno 会被设置为 EINPROGRESS,表示连接正在进行中。

当套接字连接成功或失败时,套接字会变为可写,因此应该监听写事件。

image-20240618215849407

代码如下:
image-20240618223010258

image-20240618223120134

4.并发测试工具ab

image-20240618223309231

image-20240618223710142

image-20240618223912645

image-20240619084846741

5.基于epoll的高性能服务器

epoll 是 Linux 特有的 I/O 多路复用机制,适用于处理大量并发连接。它比传统的 selectpoll 更高效,能够处理更高的并发数。

epoll 支持两种触发模式:边缘触发(Edge Triggered, ET)和水平触发(Level Triggered, LT)。

  • 水平触发(LT):

    这是 epoll 的默认模式,类似于 selectpoll 的工作方式。当文件描述符处于就绪状态时,epoll_wait 会返回该文件描述符,每次调用 epoll_wait 都会返回,直到事件被处理。

    • 优点:

      简单直接,每次都有数据时都会通知。

    • 缺点:

      当不处理事件时,epoll_wait 会不断返回就绪状态,可能导致重复处理同一事件。

  • 边缘触发(ET):

    在边缘触发模式下,当文件描述符状态发生变化(如从不可读变为可读)时,epoll_wait 会返回该文件描述符。事件只会在状态变化时触发,处理后不会再次触发,直到状态再次变化。

    • 优点:

      高效,减少了不必要的系统调用。

      适用于处理高并发连接,避免重复处理同一事件。

    • 缺点:

      复杂,需要确保每次事件处理时读取或写入尽可能多的数据,避免丢失事件。

    水平触发(level-trggered)

    • 只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就一直发出可读信号进行通知。
    • 当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知。

    边缘触发(edge-triggered)

    • 当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知。

    • 当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通知。

      水平触发是只要读缓冲区有数据,就会一直触发可读信号,而边缘触发仅仅在空变为非空的时候通知一次。

epoll的主要组件:

  1. epoll_create:创建一个 epoll 实例。
  2. epoll_ctl:控制 epoll 实例,注册、修改或删除感兴趣的文件描述符事件。
  3. epoll_wait:等待事件的发生,并返回已经准备好的文件描述符。

image-20240619171908775

image-20240619171939405

image-20240619171958914

image-20240619172023047

image-20240619172030330

注意

使用apache测试工具进行测试,发现进度卡在900条。

image-20240619172210965

主要问题在于accept部分,如果同时有多个连接到来,并且都是请求与服务器进行的连接,我们只accept一次,其他的连接就丢失了,因为我们是边缘触发,只通知一次。
image-20240619172431658

但是accept是阻塞函数,如果调用的时候没有新的连接到来了,就会一直阻塞着,因此我们需要首先设置套接字为非阻塞。

image-20240619173127635

image-20240619173141024

image-20240619162715351
处理速度是5000多次每秒,是之前的八倍。

image-20240619173048237

在if(events[i].data.fd == tcp.sock)判断条件下,可能会有多个客户端同时请求服务器,但是最开始只accept一次,会导致一些请求被丢失或者延迟处理。关于为什么设置tcp.sock为非阻塞,因为没法直接判断监听套接字队列是否为空,因此通过不停调用accept来间接判断,如果tcp.sock是阻塞,那么当队列为空,就会阻塞整个流程,导致后续只有新连接到来才会停止阻塞,反而tcp.sock为非阻塞,可以根据accept的返回值判断是否队列为空。

6.epoll、select 和阻塞 accept 之间的关系

1.监听套接字队列

当服务器调用 listen 函数将套接字设置为监听模式时,内核会为该套接字分配一个连接队列。

这个队列包含所有已完成三次握手但尚未被服务器 accept 的客户端连接。

队列与 I/O 多路复用机制(如 epoll、select 或阻塞的 accept)是独立的。

2.accept 函数

accept 函数用于从监听队列中提取一个已完成的连接,并为该连接创建一个新的套接字。

如果队列为空,阻塞模式下的 accept 函数会阻塞,直到有新的连接可用。非阻塞模式下的 accept 会立即返回,并设置 errnoEAGAINEWOULDBLOCK

3.I/O 多路复用机制

I/O 多路复用机制(如 selectpollepoll)用于监视多个文件描述符,查看它们是否准备好进行 I/O 操作(如读或写)。

六、http协议

HTTP/1.0(短连接):

  • 每个请求/响应对都要创建一个新的TCP连接,服务器在发送完响应后立即关闭连接。

HTTP/1.1(持续连接):

  • 支持持久连接,即默认情况下,TCP连接会保持打开,允许在同一个连接上发送多个请求和响应。
  • 支持分块传输编码,可以在响应主体的长度未知时逐块传输。

HTTP/2(二进制协议):

  • HTTP/2 使用二进制格式传输数据,而不是HTTP/1.1 的文本格式。
  • 在一个TCP连接上可以发送多个请求和响应,彼此互不干扰。
  • 使用HPACK压缩算法减少头部大小,降低带宽消耗。

请求

请求方法 请求地址 协议版本 回车

image-20240619190636294

image-20240619190534133

(如 epoll、select 或阻塞的 accept)是独立的。**

2.accept 函数

accept 函数用于从监听队列中提取一个已完成的连接,并为该连接创建一个新的套接字。

如果队列为空,阻塞模式下的 accept 函数会阻塞,直到有新的连接可用。非阻塞模式下的 accept 会立即返回,并设置 errnoEAGAINEWOULDBLOCK

3.I/O 多路复用机制

I/O 多路复用机制(如 selectpollepoll)用于监视多个文件描述符,查看它们是否准备好进行 I/O 操作(如读或写)。

六、http协议

HTTP/1.0(短连接):

  • 每个请求/响应对都要创建一个新的TCP连接,服务器在发送完响应后立即关闭连接。

HTTP/1.1(持续连接):

  • 支持持久连接,即默认情况下,TCP连接会保持打开,允许在同一个连接上发送多个请求和响应。
  • 支持分块传输编码,可以在响应主体的长度未知时逐块传输。

HTTP/2(二进制协议):

  • HTTP/2 使用二进制格式传输数据,而不是HTTP/1.1 的文本格式。
  • 在一个TCP连接上可以发送多个请求和响应,彼此互不干扰。
  • 使用HPACK压缩算法减少头部大小,降低带宽消耗。

请求

请求方法 请求地址 协议版本 回车

[外链图片转存中…(img-lHGhYC2W-1718795314397)]

[外链图片转存中…(img-zsc4OdXR-1718795314398)]

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

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

相关文章

【Python机器学习实战】 | Lasso回归和弹性网回归详细分析研究

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

【windows|004】BIOS 介绍及不同品牌电脑和服务器进入BIOS设置的方法

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

【BEV】BEVFormer总结

本文分享BEV感知方案中&#xff0c;具有代表性的方法&#xff1a;BEVFormer。 它基于Deformable Attention&#xff0c;实现了一种融合多视角相机空间特征和时序特征的端到端框架&#xff0c;适用于多种自动驾驶感知任务。 主要由3个关键模块组成&#xff1a; BEV Queries Q&am…

【qt5生成软件-can卡-上位机-无法加载ControlCAN.dll错误代码(0xc0150002)等相关问题-WIN11系统-尝试解决】

【qt5生成软件-无法加载ControlCAN.dll&错误代码0xc0150002&#xff1a;-等相关问题-WIN11系统-尝试解决-总结整理】 1.前言2.环境说明3.问题说明4.尝试方法总结&#xff08;1&#xff09;更新支持包c库&#xff08;2&#xff09;更新USB相关驱动&#xff08;3&#xff09;…

安装pytorch环境

安装&#xff1a;Anaconda3 通过命令行查显卡nvidia-smi 打开Anacanda prompt 新建 conda create -n pytorch python3.6 在Previous PyTorch Versions | PyTorch选择1.70&#xff0c;安装成功&#xff0c;但torch.cuda.is_available 返回false conda install pytorch1.7.0…

【golang学习之旅】使用VScode安装配置Go开发环境

1. 下载并安装Go1.1 下载地址1.2 选择版本并下载1.3 安装目录1.4 验证是否安装成功 2. 配置环境变量2.1 配置步骤2.2 GO部分环境变量说明 3. 下载或更新 Vscode3.1 下载地址3.2 安装步骤 4. 为Go开发配置VScode 1. 下载并安装Go 1.1 下载地址 https://studygolang.com/dl 1.…

【单片机】三极管的电路符号及图片识别

一&#xff1a;三极管的电路符号 二&#xff1a;三极管的分类 a;按频率分&#xff1a;高频管和低频管 b;按功率分&#xff1a;小功率管&#xff0c;中功率管和的功率管 c;按机构分&#xff1a;PNP管和NPN管 d;按材质分&#xff1a;硅管和锗管 e;按功能分&#xff1a;开关管和放…

硬盘分区无法访问:深度解析与解决之道

一、硬盘分区无法访问的现象描述 在日常使用电脑的过程中&#xff0c;有时会遇到硬盘分区无法访问的情况。这通常表现为双击分区时系统提示“无法访问”、“磁盘未格式化”或“需要格式化”等错误消息&#xff0c;导致分区内的文件无法读取或操作。这种情况可能会给用户带来极…

构建高效、便捷的家校沟通桥梁

在现代教育中&#xff0c;家校之间的有效沟通和协作是确保学生全面发展的关键。搭贝家校管理应用通过一系列强大而便捷的功能&#xff0c;帮助学校和家长实现无缝对接&#xff0c;提供全面的管理和服务。以下是搭贝家校管理应用的主要功能和优势。 &#x1f3eb; 主要功能模…

发布自己的c#包到nuget

1)创建自己的nuget账号 NuGet Gallery | Home 2)在Rider中-->项目文件夹右键-->properties 注意&#xff1a;必须勾选生成nuget包 3)编译后&#xff0c;将生成一个包 4)点击上传包 5)将之前的nuget包拖拽过来&#xff0c;点击上传即可&#xff0c;如果有不对的比如&a…

STM32开发环境搭建

新建工程 1.双击桌面的快捷方式打开STM32CubeIDE&#xff0c;需要选择一下工作空间&#xff0c;保存路径可以根据实际选择其他路径&#xff08;不要带中文&#xff09;。 点击File->New->STM32 Project. 搜索并选择芯片&#xff0c;我这里以STM32F103RCT6为例&#xff0…

python学习笔记-08

面向对象基础(OOP)-上 1. 面向对象概述 面向过程&#xff1a;根据业务逻辑从上到下写代码 函数式&#xff1a;将某功能代码封装到函数中&#xff0c;日后便无需重复编写&#xff0c;仅调用函数即可 面向对象(object oriented programming)&#xff1a;将数据与函数绑定到一起…

防爆气象站:化工厂区气象环境监测的最佳选择

在化工厂区&#xff0c;气象环境监测至关重要&#xff0c;它直接关系到生产安全、环境保护以及员工健康。防爆气象站作为专业的监测设备&#xff0c;凭借其独特的防爆性能和精准的数据监测能力&#xff0c;成为化工厂区气象环境监测的最佳选择。 防爆气象站采用先进的防爆技术…

java 线程之间通信-volatile 和 synchronized

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

Studying-代码随想录训练营day14| 226.翻转二叉树、101.对称二叉树、104.二叉树的最大深度、111.二叉树的最小深度

第十四天&#xff0c;(ง •_•)ง&#x1f4aa;&#x1f4aa;&#xff0c;编程语言&#xff1a;C 目录 226.翻转二叉树 101.对称二叉树 100.相同的树 572.另一个树的子树 104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度 总结 226.翻转二叉树 文档讲…

linux 查找和搜索命令

查找传入条件 a:在哪些目录查找 b:查找的内容 find命令: find 目录名 选项 查找条件 find /home/Camera/ -name “*.txt” 解释: /home/Camera/ 指明了查找的路径 -name 表明以名字来查找文件 *.txt 查找名为.txt的文件 grep命令: 在当前目录下查找: grep -n "sample_s…

AI辅助工具革新金融交易编程,引领行业新风尚

今天有伙伴问了我金融方面AI的问题&#xff0c;我来写一下吧 随着人工智能技术的飞速发展&#xff0c;金融交易领域也迎来了新的变革。传统的金融交易编程往往依赖于交易员的专业知识和编程技能&#xff0c;但在人工智能的助力下&#xff0c;自动写代码的AI辅助工具正逐渐崭露…

访问网络 测试没有问题,正式有问题

ping -c 5 -i 1 www.baidu.com 首先检查一下网络&#xff0c;在正式服务器ping 一下要访问的地址。 如果不行&#xff0c;联系网络管理员开通。 笔者因为这个问题浪费了半天时间&#xff0c;一开始都以为是代码问题 以后大家看到这个异常&#xff0c;解决如下&#xff1a; …

对角线法则的由来

目录 一、前言 二、对角线法则 三、行列式的定义 1. 行列式的定义 2. (全)排列 3. 逆序数 四、由全排列逆序数 到 对角线法则规律 ​编辑 五、参考书目 一、前言 仅限于个人理解&#xff0c;对错没有查证。 二、对角线法则 提起对角线法则&#xff0c;我们更倾向于他是…

企业如何选择合适的CRM工具?除Salesforce之外的10大主流选择

对比salesforce&#xff0c;其他10款优秀CRM&#xff1a;纷享销客CRM、Zoho CRM、腾讯企点、销售易、企业微信 (WeCom)、Odoo CR、OroCRM、金蝶、用友CRM、EspoCRM 虽然Salesforce以其全面的功能和强大的市场占有率在海外收获了许多客户&#xff0c;但Salesforce在国内市场的接…