从入门到精通:网络基础详解

前言

在现代社会,网络技术已经成为我们日常生活和工作中不可或缺的一部分。从简单的网页浏览到复杂的分布式系统,网络技术都扮演着至关重要的角色。通过这篇文章,读者将从入门到精通,全面掌握网络编程的理论和实践。

重点摘要

网络编程是一个复杂且多样的领域,本节将重点关注以下几个方面:

  1. 理解应用层的作用,初识HTTP协议:应用层是网络协议栈的顶层,它负责处理特定的应用程序数据。
  2. 理解传输层的作用,深入理解TCP的各项特性和机制:传输层在网络协议栈中负责数据传输的可靠性和准确性。
  3. 对整个TCP/IP协议有系统的理解:TCP/IP协议是互联网的基础,理解它的工作原理是学习网络编程的关键。
  4. 对TCP/IP协议体系下的其他重要协议和技术有一定的了解:除了TCP和UDP,还有许多其他重要的协议,如HTTP、FTP、DNS等。
  5. 学会使用一些分析网络问题的工具和方法:如Wireshark、tcpdump等工具可以帮助我们分析和解决网络问题。

这些内容不仅是网络编程的理论基础,也是服务器开发程序员的重要基本功,更是各大公司笔试面试的核心考点。

应用层

应用层是网络协议栈的顶层,负责处理特定的应用程序数据。我们日常使用的许多网络应用程序,如浏览器、邮件客户端、聊天软件等,都是在应用层运行的。

再谈“协议”

协议是一种“约定”,是通信双方遵循的规则和标准。在网络编程中,socket API提供了读写数据的接口,这些接口通常以“字符串”的方式来发送接收数据。但如果我们需要传输“结构化的数据”怎么办呢?

网络版计算器

例如,我们需要实现一个服务器版的加法器。客户端需要发送两个加数,服务器进行计算后再返回结果给客户端。我们可以采用以下两种方案:

方案一

  • 客户端发送一个形如“1+1”的字符串;
  • 字符串中有两个操作数,都是整形;
  • 两个数字之间有一个字符是运算符,运算符只能是“+”;
  • 数字和运算符之间没有空格;

这种方法的优点是实现简单,但缺点是扩展性差。如果需要增加其他运算符或支持浮点数计算,就需要修改协议和解析逻辑。

方案二

  • 定义结构体来表示交互的信息;
  • 发送数据时将结构体按照一定规则转换成字符串,接收数据时再按照相同规则将字符串转化回结构体;
  • 这个过程叫做“序列化”和“反序列化”。
// proto.h 定义通信的结构体
typedef struct Request {
    int a;
    int b;
} Request;

typedef struct Response {
    int sum;
} Response;

// client.c 客户端核心代码
Request request;
Response response;

scanf("%d,%d", &request.a, &request.b);
write(fd, &request, sizeof(Request));
read(fd, &response, sizeof(Response));

// server.c 服务端核心代码
Request request;
read(client_fd, &request, sizeof(request));
Response response;
response.sum = request.a + request.b;
write(client_fd, &response, sizeof(response));

这种方法的优点是扩展性强,可以很容易地增加新的字段和功能,但缺点是需要额外的序列化和反序列化过程,增加了编程复杂度。

无论采用哪种方案,只要保证一端发送的数据能够在另一端正确解析,就可以认为协议是成功的。这种约定,就是应用层协议。

HTTP协议

虽然应用层协议是我们程序员自己定的,但实际上,已经有很多前辈定义了一些现成的、非常好用的应用层协议供我们直接使用。HTTP(超文本传输协议)就是其中之一。

认识URL

平时我们俗称的“网址”其实就是URL(Uniform Resource Locator,统一资源定位符)。URL是用来标识互联网上的资源的地址。一个完整的URL包括以下几个部分:

  1. 协议:如http、https、ftp等;
  2. 主机名:如www.example.com;
  3. 端口号:默认为80(HTTP)或443(HTTPS),但可以指定其他端口;
  4. 路径:如/index.html,表示资源在服务器上的位置;
  5. 查询参数:如?name=John&age=30,用于传递额外的信息;
  6. 片段标识符:如#section1,用于标识页面内的特定位置。
urlencode和urldecode

在URL中,某些字符(如“/”、“?”、“:”等)有特殊意义,因此不能随意出现。如果某个参数需要包含这些特殊字符,就必须先对其进行转义。转义规则如下:

  • 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。
  • 例如:“+”被转义成了“%2B”。
import urllib.parse

original_string = "Hello World!"
encoded_string = urllib.parse.quote(original_string)
decoded_string = urllib.parse.unquote(encoded_string)

print("Original:", original_string)
print("Encoded:", encoded_string)
print("Decoded:", decoded_string)

urldecode就是urlencode的逆过程,用于将转义后的字符还原成原始字符。这个过程在实际应用中非常常见,特别是在处理GET请求的参数时。

HTTP协议格式

HTTP请求和响应的格式包括三部分:首行、Header和Body。

HTTP请求

  • 首行:[方法] + [URL] + [版本],例如“GET /index.html HTTP/1.1”;
  • Header:请求的属性,以冒号分割的键值对,每组属性之间用\n分隔,遇到空行表示Header部分结束;
  • Body:空行后面的内容都是Body,Body允许为空字符串,如果存在Body,则在Header中会有一个Content-Length属性来标识Body的长度。

HTTP响应

  • 首行:[版本号] + [状态码] + [状态码解释],例如“HTTP/1.1 200 OK”;
  • Header:响应的属性,以冒号分割的键值对,每组属性之间用\n分隔,遇到空行表示Header部分结束;
  • Body:空行后面的内容都是Body,Body允许为空字符串,如果存在Body,则在Header中会有一个Content-Length属性来标识Body的长度。
HTTP的方法

HTTP定义了一系列方法,用于指定对资源执行的操作。常见的方法包括:

  • GET:请求获取指定资源,通常用于获取网页内容;
  • POST:向指定资源提交数据进行处理,常用于提交表单数据;
  • PUT:向指定资源位置上传最新内容,常用于更新资源;
  • DELETE:删除指定资源,常用于删除服务器上的资源;
  • HEAD:类似GET方法,但只请求资源的头部信息,不返回实际内容;
  • OPTIONS:请求指定资源的通信选项和需求,通常用于跨域请求的预检;
  • PATCH:对指定资源进行部分修改,常用于更新资源的一部分。
HTTP的状态码

HTTP状态码用于表示服务器对请求的处理结果。常见的状态码包括:

  • 1xx(信息性状态码)
    • 100 Continue:客户端应继续请求。
  • 2xx(成功状态码)
    • 200 OK:请求成功。
    • 201 Created:请求成功并创建了新的资源。
  • 3xx(重定向状态码)
    • 301 Moved Permanently:资源永久移动到新位置。
    • 302 Found:资源临时移动到新位置。
  • 4xx(客户端错误状态码)
    • 400 Bad Request:请求无效。
    • 401 Unauthorized:未授权。
    • 403 Forbidden:禁止访问。
    • 404 Not Found:请求的资源不存在。
  • 5xx(服务器错误状态码)
    • 500 Internal Server Error:服务器内部错误。
    • 502 Bad Gateway:无效网关。
    • 503 Service Unavailable:服务不可用。
HTTP常见Header

Header是HTTP请求和响应的重要组成部分,用于传递请求和响应的元数据。常见的HTTP Header包括:

  • Content-Type:表示数据类型(如text/html、application/json等);
  • Content-Length:表示Body的长度;
  • Host:客户端告知服务器,请求的资源在哪个主机的哪个端口上;
  • User-Agent:声明用户的操作系统和浏览器版本信息;
  • Referer:当前页面是从哪个页面跳转过来的;
  • Location:搭配

3xx状态码使用,告诉客户端接下来要去哪里访问;

  • Cookie:用于在客户端存储少量信息,通常用于实现会话(session)的功能。

User-Agent里的历史故事:User-Agent最早是用于表示浏览器的版本信息,但随着浏览器的更新换代,这个字段也变得越来越复杂。例如,早期的浏览器如Netscape和Internet Explorer都有各自的User-Agent字符串,但随着时间的推移,许多浏览器开始模仿这些字符串以提高兼容性。

最简单的HTTP服务器

实现一个最简单的HTTP服务器,只在网页上输出“hello world”。只要我们按照HTTP协议的要求构造数据,就很容易实现。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void Usage() {
  printf("usage: ./server [ip] [port]\n");
}

int main(int argc, char* argv[]) {
  if (argc != 3) {
    Usage();
    return 1;
  }
  int fd = socket(AF_INET, SOCK_STREAM, 0);
  if (fd < 0) {
    perror("socket");
    return 1;
  }
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = inet_addr(argv[1]);
  addr.sin_port = htons(atoi(argv[2]));

  int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
  if (ret < 0) {
    perror("bind");
    return 1;
  }
  ret = listen(fd, 10);
  if (ret < 0) {
    perror("listen");
    return 1;
  }
  for (;;) {
    struct sockaddr_in client_addr;
    socklen_t len;
    int client_fd = accept(fd, (struct sockaddr*)&client_addr, &len);
    if (client_fd < 0) {
      perror("accept");
      continue;
    }
    char input_buf[1024 * 10] = {0};  // 用一个足够大的缓冲区直接把数据读完。
    ssize_t read_size = read(client_fd, input_buf, sizeof(input_buf) - 1);
    if (read_size < 0) {
      return 1;
    }
    printf("[Request] %s", input_buf);
    char buf[1024] = {0};
    const char* hello = "<h1>hello world</h1>";
    sprintf(buf, "HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s", strlen(hello), hello);
    write(client_fd, buf, strlen(buf));
  }
  return 0;
}

备注:

  • 此处使用9090端口号启动了HTTP服务器。虽然HTTP服务器一般使用80端口,但这只是一个通用的习惯,并不是说HTTP服务器就不能使用其他的端口号。
  • 使用Chrome测试我们的服务器时,可以看到服务器打出的请求中还有一个“GET /favicon.ico HTTP/1.1”这样的请求。读者可以自行查找资料,理解favicon.ico的作用。

实验:把返回的状态码改成404、403、504等,观察浏览器上的效果。

传输层

传输层负责确保数据能够从发送端可靠地传输到接收端。传输层的两个主要协议是TCP和UDP。

再谈端口号

端口号(Port)标识了一个主机上进行通信的不同应用程序。在TCP/IP协议中,用“源IP”、“源端口号”、“目的IP”、“目的端口号”、“协议号”这样一个五元组来标识一个通信。

端口号范围划分
  • 0 - 1023:知名端口号,HTTP、FTP、SSH等这些广为使用的应用层协议的端口号都是固定的。
  • 1024 - 65535:操作系统动态分配的端口号,客户端程序的端口号由操作系统从这个范围分配。
认识知名端口号(Well-Known Port Number)

有些服务器非常常用,为了使用方便,人们约定一些常用服务器使用以下固定的端口号:

  • SSH服务器,使用22端口;
  • FTP服务器,使用21端口;
  • Telnet服务器,使用23端口;
  • HTTP服务器,使用80端口;
  • HTTPS服务器,使用443端口。

我们自己写程序使用端口号时,要避开这些知名端口号。

两个问题
  1. 一个进程是否可以bind多个端口号?
  2. 一个端口号是否可以被多个进程bind?

这些问题可以通过实验和查阅相关文档来验证。

netstat

netstat是一个用来查看网络状态的重要工具。

常用选项

  • n:拒绝显示别名,能显示数字的全部转化成数字;
  • l:仅列出有在Listen(监听)的服务状态;
  • p:显示建立相关链接的程序名;
  • t:仅显示TCP相关选项;
  • u:仅显示UDP相关选项;
  • a:显示所有选项,默认不显示LISTEN相关。
pidof

pidof是一个在查看服务器的进程ID时非常方便的工具。

语法pidof [进程名]
功能:通过进程名查看进程ID。

UDP协议

UDP(User Datagram Protocol,用户数据报协议)是一种无连接、不可靠的传输层协议。

UDP协议端格式

UDP协议头包括以下字段:

  • 源端口号:16位,表示发送数据的应用程序的端口号;
  • 目的端口号:16位,表示接收数据的应用程序的端口号;
  • 长度:16位,表示整个UDP数据报的长度(包括UDP头和数据部分);
  • 校验和:16位,用于错误检测。
UDP的特点
  • 无连接:知道对端的IP和端口号就可以直接进行传输,不需要建立连接;
  • 不可靠:没有确认机制和重传机制,如果因为网络故障数据无法到达对方,UDP协议层不会返回任何错误信息;
  • 面向数据报:不能灵活控制读写数据的次数和数量,应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。
UDP的缓冲区
  • UDP没有真正意义上的发送缓冲区。调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;
  • UDP具有接收缓冲区,但不能保证收到的UDP报文的顺序和发送顺序一致。如果缓冲区满了,再到达的UDP数据就会被丢弃。
UDP使用注意事项
  • UDP协议首部中的最大长度为16位,即一个UDP报文的最大长度是64K(包含UDP首部)。
  • 如果需要传输的数据超过64K,就需要在应用层手动分包,多次发送,并在接收端手动拼装。
基于UDP的应用层协议
  • NFS:网络文件系统
  • TFTP:简单文件传输协议
  • DHCP:动态主机配置协议
  • BOOTP:启动协议(用于无盘设备启动)
  • DNS:域名解析协议

TCP协议

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接、可靠的传输层协议。

TCP协议段格式

TCP协议头包括以下字段:

  • 源/目的端口号:16位,表示数据从哪个进程来,到哪个进程去;
  • 序号:32位,用于标识数据段的顺序;
  • 确认号:32位,表示已成功接收的数据段序号;
  • 头部长度:4位,表示TCP头部的长度;
  • 标志位:6位,包括URG、ACK、PSH、RST、SYN、FIN;
  • 窗口大小:16位,用于流量控制;
  • 校验和:16位,用于错误检测;
  • 紧急指针:16位,标识紧急数据的位置;
  • 选项:可选字段,用于扩展TCP功能。
确认应答(ACK)机制

TCP将每个字节的数据都进行了编号,即为序列号。每一个ACK都带有对应的确认序列号,告诉发送者哪些数据已被接收,下一次从哪里开始发送。

超时重传机制

如果发送的数据在特定时间内没有收到确认应答,发送端会进行重发。这个时间间隔根据网络环境动态计算。

连接管理机制

TCP要经过三次握手建立连接,四次挥手断开连接。连接建立和断开的具体流程如下:

服务端状态转换

  • CLOSED -> LISTEN:服务器端调用listen后进入LISTEN状态,等待客户端连接;
  • LISTEN -> SYN_RCVD:监听到连接请求后,进入SYN_RCVD状态,并向客户端发送SYN确认报文;
  • SYN_RCVD -> ESTABLISHED:收到客户端确认报文后,进入ESTABLISHED状态,可以进行数据读写;
  • ESTABLISHED

-> CLOSE_WAIT:客户端主动关闭连接,服务器收到结束报文段后进入CLOSE_WAIT状态;

  • CLOSE_WAIT -> LAST_ACK:服务器调用close关闭连接后,发送FIN报文,进入LAST_ACK状态,等待客户端确认;
  • LAST_ACK -> CLOSED:收到客户端的确认后,彻底关闭连接。

客户端状态转换

  • CLOSED -> SYN_SENT:客户端调用connect,发送同步报文段;
  • SYN_SENT -> ESTABLISHED:connect调用成功后进入ESTABLISHED状态,开始数据读写;
  • ESTABLISHED -> FIN_WAIT_1:客户端主动调用close时,向服务器发送结束报文段,进入FIN_WAIT_1;
  • FIN_WAIT_1 -> FIN_WAIT_2:收到服务器确认后进入FIN_WAIT_2,等待服务器的结束报文段;
  • FIN_WAIT_2 -> TIME_WAIT:收到服务器的结束报文段后,进入TIME_WAIT,发送最后的ACK;
  • TIME_WAIT -> CLOSED:等待2MSL(Max Segment Life,报文最大生存时间)后,进入CLOSED状态。
理解TIME_WAIT状态

TCP协议规定,主动关闭连接的一方要处于TIME_WAIT状态,等待两个MSL的时间后才能回到CLOSED状态。这是为了保证最后一个报文可靠到达,防止重启服务器时收到错误的迟到数据。

解决TIME_WAIT状态引起的bind失败的方法

在某些情况下,服务器需要处理大量客户端连接,每个连接的生存时间很短,但连接请求频繁。此时,可以使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1,允许创建端口号相同但IP地址不同的多个socket描述符。

理解CLOSE_WAIT状态

如果服务器上出现大量CLOSE_WAIT状态,说明服务器没有正确关闭socket,导致四次挥手没有正确完成。只需要在合适的位置加上close()即可解决问题。

滑动窗口

滑动窗口机制允许发送端在未收到确认应答前发送多个数据段,大大提高了传输效率。窗口大小表示无需等待确认应答而可以继续发送数据的最大值。窗口越大,网络的吞吐率越高。

流量控制

接收端通过TCP头部中的窗口大小字段告知发送端当前缓冲区的剩余空间,发送端根据窗口大小调整发送速度,防止缓冲区溢出。

拥塞控制

TCP引入慢启动机制,在不清楚网络状态的情况下,先发少量数据探测,逐步增加发送量。拥塞窗口(cwnd)初始为1,每次收到ACK后增加1,超过慢启动阈值后,按线性增长。

延迟应答和捎带应答

延迟应答通过稍微延迟ACK的发送时间,增加窗口大小,提高传输效率。捎带应答则利用应用层的响应数据捎带ACK一起发送。

面向字节流

TCP连接在内核中维护一个发送缓冲区和接收缓冲区,数据在缓冲区中进行处理,保证传输的可靠性和顺序性。TCP连接是全双工的,既可以读数据,也可以写数据。

粘包问题

粘包问题是指应用层看到的一串连续字节数据中无法区分出每个完整的数据包。解决方法包括:

  • 对于定长包,按照固定大小读取;
  • 对于变长包,在包头约定一个包总长度字段或使用明确的分隔符。

TCP异常情况

  • 进程终止:释放文件描述符,发送FIN,正常关闭连接。
  • 机器重启:与进程终止相同。
  • 机器掉电/网线断开:接收端发现连接已断开,进行重置或通过保活定时器释放连接。

TCP小结

TCP通过一系列复杂的机制保证传输的可靠性和高效性。这些机制包括校验和、序列号、确认应答、超时重发、连接管理、流量控制和拥塞控制等。

基于TCP的应用层协议

  • HTTP
  • HTTPS
  • SSH
  • Telnet
  • FTP
  • SMTP

当然,还包括我们自己定义的应用层协议。

TCP/UDP对比

TCP和UDP各有优缺点,适用于不同的场景。TCP适用于可靠传输,如文件传输和重要状态更新;UDP适用于对高速传输和实时性要求较高的通信,如视频传输和广播。

用UDP实现可靠传输(经典面试题)

参考TCP的可靠性机制,在应用层实现类似的逻辑,包括序列号、确认应答和超时重传等。

TCP相关实验

通过实验理解listen的第二个参数、使用Wireshark分析TCP通信流程等,进一步掌握TCP协议的工作原理和实际应用。

理解 listen 的第二个参数

在TCP服务器编程中,listen函数的第二个参数表示监听队列的最大长度。这个参数的值决定了内核为该套接字维护的两个队列的长度:

  • 半连接队列(SYN Queue):存放处于SYN_RECV状态的连接请求。
  • 全连接队列(Accept Queue):存放已完成三次握手,但应用程序尚未调用accept取走的连接。

当一个新的连接请求到达时,内核首先将其放入半连接队列。如果客户端发送的SYN报文被确认,连接进入全连接队列。如果全连接队列已满,新的连接请求将被拒绝。

#include "tcp_socket.hpp"

int main(int argc, char* argv[]) {
  if (argc != 3) {
    printf("Usage ./test_server [ip] [port]\n");
    return 1;
  }
  TcpSocket sock;
  bool ret = sock.Bind(argv[1], atoi(argv[2]));
  if (!ret) {
    return 1;
  }
  ret = sock.Listen(2);
  if (!ret) {
    return 1;
  }
  // 客户端不进行 accept
  while (1) {
    sleep(1);
  }
  return 0;
}

使用 Wireshark 分析 TCP 通信流程

Wireshark是一个强大的网络协议分析工具,可以抓取和分析网络通信数据包。以下是使用Wireshark分析TCP通信流程的步骤:

下载和安装 Wireshark

可以从Wireshark官方网站下载并安装最新版本的Wireshark。

启用 telnet 客户端

在Windows上启用telnet客户端,参考百度经验。

启动 Wireshark 并设置过滤器

启动Wireshark后,在过滤器栏中输入ip.addr == [服务器 ip]tcp.port == 9090,以只抓取指定IP或端口的数据包。

观察三次握手过程

启动服务器后,使用telnet客户端连接服务器,抓取数据包并观察三次握手过程。可以看到三个报文各自的序列号和确认序号的规律。

telnet [ip] [port]
观察确认应答

在telnet中输入一个字符,可以看到客户端发送一个长度为1字节的数据,服务器返回ACK和响应数据,然后客户端反馈ACK。

观察四次挥手

在telnet中输入ctrl + ]回到控制界面,输入quit退出,可以观察四次挥手的过程。

结语

网络基础是现代计算机科学的重要组成部分,掌握网络编程的理论和实践,不仅有助于理解计算机系统的运行机制,还能提高开发高性能、可靠网络应用的能力。希望本篇文章能帮助读者从入门到精通,全面掌握网络基础知识。
嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。
觉得有点收获的话,不妨给我点个吧!
如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~

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

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

相关文章

2024年电脑监控软件排行榜(真实测评推荐七款电脑监控软件)

在信息化快速发展的今天&#xff0c;企业对员工电脑活动的监控变得尤为重要。有效的电脑监控软件不仅可以提升员工的工作效率&#xff0c;还能防止信息泄露&#xff0c;保障企业的数据安全。本文将介绍几款知名的电脑监控软件&#xff0c;并对其特点进行详细分析&#xff0c;帮…

JavaWeb系列二十三: web 应用常用功能(文件上传下载)

文章目录 5. 文件上传基本介绍5.1 文件上传-原理示意图5.2 文件上传页面5.3 走通Servlet5.4 表单项区别处理5.5 创建目录-保存文件5.6 中文编码问题5.7 文件上传注意事项和细节5.7.1 按照年月日目录存放5.7.2 文件覆盖问题5.7.3 封装一下 5.8 文件上传其他注意事项5.8.1 upload…

浅谈信息技术高效课堂管理:策略、技巧与实践

引言&#xff1a; 在信息化教育的浪潮中&#xff0c;信息技术课程正逐渐成为学校教育体系中的重要组成部分。然而&#xff0c;信息技术课堂的特殊性——高互动性、高度依赖电子设备&#xff0c;给课堂管理带来了前所未有的挑战。如何在保证教学效率的同时&#xff0c;维护良好…

go mod 依赖管理补充2

依赖包的版本问题&#xff0c;别的开发语言有没有类似的问题&#xff1f;是怎么解决的&#xff1f; 举例&#xff1a;java java的依赖包的版本问题&#xff0c;通过Maven模块来操作&#xff0c;可以指定依赖包版本号&#xff0c;如下&#xff1a; go.mod 文件 go.mod文件是G…

VS2019运行显示缺少调试目标

出现问题点 如果点击运行显示上述错误&#xff0c;可以尝试先清理&#xff0c;然后重新生成 此时会出来一个调试目标路径&#xff0c;代表生成成功 但是运行还是显示缺少调试目标 右键项目&#xff0c;点击属性&#xff0c;然后修改路径&#xff0c;既可成功

谷粒商城学习笔记-19-快速开发-逆向生成所有微服务基本CRUD代码

文章目录 一&#xff0c;使用逆向工程步骤梳理1&#xff0c;修改逆向工程的application.yml配置2&#xff0c;修改逆向工程的generator.properties配置3&#xff0c;以Debug模式启动逆向工程4&#xff0c;使用逆向工程生成代码5&#xff0c;整合生成的代码到对应的模块中 二&am…

paddleocr运行报错?谈谈解决思路。

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

【网安播报】CocoaPods 曝关键漏洞,应用程序面临供应链攻击风险

1、CocoaPods 曝关键漏洞&#xff0c;数百万 macOS 和 iOS 应用程序面临供应链攻击风险 开源依赖管理器 CocoaPods 中的安全漏洞暴露了数千个软件包&#xff0c;利用这些漏洞的攻击者可以将恶意代码注入合法应用&#xff0c;通过受信任的渠道分发恶意软件&#xff0c;并破坏用户…

Python前沿技术:机器学习与人工智能

Python前沿技术&#xff1a;机器学习与人工智能 一、引言 随着科技的飞速发展&#xff0c;机器学习和人工智能&#xff08;AI&#xff09;已经成为了计算机科学领域的热门话题。Python作为一门易学易用且功能强大的编程语言&#xff0c;已经成为了这两个领域的首选语言之一。本…

私有化要约溢价60%,欧舒丹与投资者的相互成就

港股市场迎来新一轮私有化浪潮。据上海证券报不完全统计&#xff0c;自2023年以来&#xff0c;已有19家港股上市公司完成私有化退市。 对于深陷港股低估值困境的投资者来说&#xff0c;持仓名单里有公司宣布高溢价私有化要约&#xff0c;可谓“喜大普奔”的消息。 上市公司私…

A股周一低开低走,行情继续炸裂!

今天的A股&#xff0c;让人揪心不已、心情极度炸裂&#xff0c;你们知道是为什么吗&#xff1f;盘面上出现2个重要信号&#xff0c;一起来看看&#xff1a; 1、今天两市低开低走&#xff0c;A股又是绿油油的一天&#xff0c;两市近4800家个股在等待着上涨。近一个多月来&#…

快速掌握AI的最佳途径实践

科技时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为许多人希望掌握的重要技能。对于普通人来说&#xff0c;如何快速有效地学习AI仍然是一个挑战。本文将详细介绍几种快速掌握AI的途径&#xff0c;并提供具体的操作步骤和资源建议。 前言 AI的普及和应用已经深…

FL Studio 2024 发布,添加 FL Cloud 插件、AI 等功能

作为今年最受期待的音乐制作 DAW 更新之一&#xff0c;FL Studio 2024发布引入了新功能&#xff0c;同时采用了新的命名方式&#xff0c;从现在起将把发布年份纳入其名称中。DAW 的新增功能包括在 FL Cloud 中添加插件、AI 驱动的音乐创作工具和 FL Studio 的新效果。 FL Cloud…

国内知名源码交易平台及其特点,建议收藏!

​在数字化时代&#xff0c;源码交易平台成为连接开发者与项目需求的重要桥梁。这些平台不仅提供了丰富的源码资源&#xff0c;还促进了技术交流与合作。本文小编将分享介绍几个国内知名的源码交易平台&#xff0c;包括帮企商城、春哥技术博客、86资源网、春哥技术源码论坛以及…

年销量超1亿箱,三得利BOSS咖啡如何凭借人群战略打造极致产品力?

BOSS咖啡诞生于1992年&#xff0c;在可口可乐、朝日、麒麟等饮料巨头先后入局&#xff0c;市场竞争非常激烈的情况下&#xff0c;BOSS咖啡成为受国民欢迎的品牌&#xff0c;它是如何做到的呢? 罐装咖啡趋势崛起&#xff0c;各大品牌推出罐装咖啡 自1980年代起&#xff0c;罐装…

2024世界人工智能大会|实在智能孙林君分享实在Agent创新应用与落地进展

近日&#xff0c;2024世界人工智能大会&#xff08;WAIC 2024&#xff09;在上海举办&#xff0c;汇聚了9位图灵奖、菲尔兹奖、诺贝尔奖得主、88位国内外院士及超过1000位全球全球领军人物&#xff0c;共同探讨AI伦理治理、大模型、数据、算力等前沿议题&#xff0c;把握AI带来…

java-spring boot光速入门教程(超详细!!)

目录 一、引言 1.1 初始化配置 1.2 整合第三方框架 1.3 后期维护 1.4 部署工程 1.5 敏捷式开发 二、SpringBoot介绍 spring boot 2.1 搭建一个spring boot工程 2.2 使用idea创建项目 2.3 在线创建姿势 2.4 项目的目录结构 2.5 项目的运行方式 2.6 yml文件格式 2…

网络资源模板--Android Studio 外卖点餐App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 原创外卖点餐&#xff1a;基于Android studio 实现外卖(点)订餐系统 非原创奶茶点餐&#xff1a;网络资源模板--基于 Android Studio 实现的奶茶点餐App报告 一、项目演示 网络资源模板--基于Android …

数字化设计与分析助力建造印度最大污水处理厂

利用 STAAD 开展结构分析和设计&#xff0c;为不稳定土体上的复杂水池系统开发稳定的基础 治理河流 新德里不仅是印度的首都&#xff0c;一个多世纪以来也一直是印度最重要的城市之一。这座城市于 1911 年作为新的政府所在地&#xff0c;历经 20 年时间建成了许多宏伟建筑&…

LlamaGen:自回归模型的图像生成革命

LlamaGen&#xff1a;自回归模型的图像生成革命 1. 突破性进展&#xff1a;LlamaGen超越传统扩散模型 在图像生成领域&#xff0c;LlamaGen团队带来了颠覆性创新。由香港大学和字节跳动的研究人员共同开发的这一模型&#xff0c;不仅在技术上超越了传统的扩散模型&#xff0c;…