网络基础概念和 socket 编程

网络基础概念和 socket 编程

学习目标

  • 了解 OSI 七层模型、TCP/IP 四层模型结构
  • 了解常见的网络协议格式
  • 掌握网络字节序和主机字节序之间的转换
  • 理解 TCP 服务器端通信流程
  • 理解 TCP 客户端通信流程
  • 实现 TCP 服务器端和客户端的代码

推荐一个非常好的学习资料仓库

协议

协议的概念

协议是事先约定好,大家共同遵守的一组规则,如交通信号灯。从应用的角度出发,协议可理解为“规则”,是数据传输和数据的解释的规则,可以简单的理解为各个主机之间进行通信所使用的共同语言。

假设,主机 A、主机 B 双方欲传输文件,规定:

  • 第一次,传输文件名,接收方接收到文件名,应答 OK 给传输方
  • 第二次,发送文件的尺寸,接收方接收到该数据再次应答一个 OK
  • 第三次,传输文件内容,接收方接收数据完成后应答 OK 表示文件内容接收成功
    在这里插入图片描述

由此,无论 A、B 之间传递何种文件,都是通过三次数据传输来完成。A、B 之间形成了一个最简单的数据传输规则。双方都按此规则发送、接收数据。A、B 之间达成的这个相互遵守的规则即为协议。

这种仅在 A、B 之间被遵守的协议称之为原始协议。当此协议被更多的人采用,不断的增加、改进、维护、完善。最终形成一个稳定的、完整的文件传输协议,被广泛应用于各种文件传输过程中。该协议就成为一个标准协议。最早的 ftp 协议就是由此衍生而来。

典型的协议

实际生活中有以下几种常见的协议:

  • 应用层常见的协议有 HTTP 协议、FTP 协议等
    • HTTP:超文本传输协议(Hyper Text Transfer Protocol),是互联网上应用最广泛的一种网络协议
    • FTP:文件传输协议(File Transfer Protocol)
  • 传输层常见的协议有 TCP/UDP 协议
    • TCP:传输控制协议(Transmission Control Protocol),是一种面向连接的、可靠的、基于字节流的传输层通信协议
    • UDP:用户数据协议(User Datagram Protocol),是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务
  • 网络层常见的协议有 IP 协议、ICMP 协议、IGMP 协议
    • IP:因特网互联协议(Internet Protocol)
    • ICMP:Internet 控制报文协议(Internet Control Message Protocol),是 TCP/IP 协议族的一个子协议,用于在 IP 主机、路由器之间传递控制消息
    • IGMP:Internet 组管理协议(Internet Group Management Protocol),是因特网协议家族中的一个组播协议,该协议运行在主机和组播路由器之间
  • 网络接口层常见的协议有 ARP 协议、RARP 协议
    • ARP:正向地址解析协议(Address Resolution Protocol),通过已知的 IP,寻找对应主机的 MAC 地址
    • RARP:反向地址转换协议,通过 MAC 地址确定 IP 地址

网络模型

OSI 七层模型

OSI 七层模型是国际标准组织制定的 OSI 理论模型,该模型定义了不同计算机互联的标准, 是设计和描述计算机网络通信的基本框架。七层模型分别是以下几个(从上向下):

  • 应用层:是最靠近用户的 OSI 层,这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务
  • 表示层:可确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。例如,PC 程序与另一台计算机进行通信,其中一台计算机使用扩展二一十进制交换码(EBCDIC),而另一台则使用美国信息交换标准码(ASCII)来表示相同的字符。如有必要,表示层会通过使用一种通格式来实现多种数据格式之间的转换
  • 会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)
  • 传输层:定义了一些传输数据的协议和端口号(WWW 端口 80 等),主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组,常常把这一层数据叫做段
  • 网络层:在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择。Internet 的发展使得从世界各站点访问信息的用户数大大增加,而网络层正是管理这种连接的层
  • 数据链路层:定义了如何让格式化数据以帧为单位进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输。如:串口通信中使用到的 115200、8、N、1
  • 物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由 1、0 转化为电流强弱来进行传输,到达目的地后再转化为 1、0,也就是我们常说的数模转换与模数转换),这一层的数据叫做比特

在这里插入图片描述

TCP/IP 四层模型

在实际生产开发中,讨论更多的是 TCP/IP 四层模型,这是对七层模型的简化

在这里插入图片描述

TCP/IP 网络协议栈分为应用层(Application)、传输层(Transport)、网络层(Network)和链路层(Link)四层,如下图所示:

在这里插入图片描述

数据通信过程

数据的通信过程本质上在发送方是一个层层打包的过程,在接收方是一个层层解包的过程,这种打包的过程是内核帮我们完成。如下图所示,PC 机 A 通过网络向 PC 机 B 发送数据的过程

在这里插入图片描述

网络应用程序设计模式

目前使用最多的设计模式就两种 C/S 和 B/S:

  • C/S:客户端和服务器模式,需要在通讯两端各自部署客户机和服务器来完成数据通信
    • 优点:客户端在本机上可以保证性能,可以将数据缓存到本地,提高数据的传输效率,提高用户体验效果;客户端和服务端程序都是由同一个开发团队开发,协议选择比较灵活
    • 缺点:服务器和客户端都需要开发,工作量相对较大,调试困难,开发周期长;从用户的角度看,需要将客户端安装到用户的主机上,对用户主机的安全构成威胁
  • B/S:浏览器和服务器模式,只需在一端部署服务器,而另一端使用浏览器即可完成数据传输
    • 优点:无需安装客户端,可以使用标注你的浏览器作为客户端;只需要开发服务器,工作量相对较小;由于采用标准的客户端,所以移植性好,不受平台限制;相对安全,不用安装软件
    • 缺点:由于没有客户端,数据缓冲不尽人意,数据传输有限制,用户体验较差;通信协议选择只能使用 HTTP 协议,协议选择不够灵活

以太网帧

以太网帧格式就是包装在网络接口层(数据链路层)的协议,具体格式如下:

在这里插入图片描述

以 ARP 为例,其协议格式具体如下:
在这里插入图片描述

源 MAC 地址、目的 MAC 地址在以太网首部和 ARP 请求中各出现一次,对于链路层为以太网的情况是多余的,但如果链路层是其它类型的网络则有可能是必要的。硬件类型指链路层网络类型,1 为以太网,协议类型指要转换的地址类型,0x0800 为 IP 地址,后面两个地址长度对于以太网地址和IP地址分别为 6 和 4(字节),op 字段为 1 表示 ARP 请求,op 字段为 2 表示 ARP 应答。

假设现在 PC 机 A 向 PC 机 B 发送请求,简单的流程如下:

  • PC 机 A 将本机的 MAC 地址填入源地址,以广播的方式发送 ARP 报文,因此数据报文的格式为
    • 以太网首部(14字节):0000: ff ff ff ff ff ff 00 05 5d 61 58 a8 08 06 —— 目的主机采用广播地址,源主机的 MAC 地址是00:05:5d:61:58:a8,上层协议类型 0x0806 表示 ARP
    • ARP 帧(28 字节):
      • 0000: 00 01 —— 硬件类型 0x0001 表示以太网
      • 0010: 08 00 06 04 00 01 00 05 5d 61 58 a8 c0 a8 00 37 —— 协议类型 0x0800 表示 IP 协议,硬件地址(MAC地址)长度为 6,协议地址(IP地址)长度为 4,op 为 0x0001 表示请求目的主机的 MAC 地址,源主机 MAC 地址为 00:05:5d:61:58:a8,源主机 IP 地址为 c0 a8 00 37(192.168.0.55)
      • 0020: 00 00 00 00 00 00 c0 a8 00 02 —— 目的主机 MAC 地址全 0 待填写,目的主机 IP 地址为 c0 a8 00 02(192.168.0.2)
    • 填充位(18 字节):由于以太网规定最小数据长度为46字节,ARP帧长度只有28字节,因此有18字节填充位,填充位的内容没有定义,与具体实现相关
      • 0020: 00 77 31 d2 50 10
      • 0030: fd 78 41 d3 00 00 00 00 00 00 00 00
  • PC 机 B 收到 ARP 数据报文后,发送应答
    • 以太网首部(14字节):0000: 00 05 5d 61 58 a8 00 05 5d a1 b8 40 08 06 —— 目的主机的 MAC 地址是00:05:5d:61:58:a8,源主机的 MAC 地址是 00:05:5d:a1:b8:40,上层协议类型 0x0806 表示 ARP
    • ARP 帧(28 字节):
      • 0000: 00 01 —— 硬件类型 0x0001 表示以太网
      • 0010: 08 00 06 04 00 02 00 05 5d a1 b8 40 c0 a8 00 02 —— 协议类型 0x0800 表示 IP 协议,硬件地址(MAC地址)长度为 6,协议地址(IP地址)长度为 4,op 为 0x0002 表示应答,源主机 MAC 地址为 00:05:5d:a1:b8:40,源主机 IP 地址为 c0 a8 00 02(192.168.0.2)
      • 0020: 00 05 5d 61 58 a8 c0 a8 00 37 —— 目的主机MAC地址为 00:05:5d:61:58:a8,目的主机 IP 地址为c0 a8 00 37(192.168.0.55)
    • 填充位(18 字节):
      • 0020: 00 77 31 d2 50 10
      • 0030: fd 78 41 d3 00 00 00 00 00 00 00 00

其他的数据包格式也以差不多的方式进行发送和应答。

注意:通过 IP 地址可以确定同一网段中唯一的一台主机,主机使用端口号来区分不同的应用程序。

socket 编程

传统的进程间通信借助内核提供的IPC机制进行,但是只能限于本机通信,若要跨机通信,就必须使用网络通信(本质上借助内核-内核提供了 socket 伪文件的机制实现通信——实际上是使用文件描述符),这就需要用到内核提供给用户的 socket API 函数库。

网络字节序

在进行网络通信时,一定要注意数据的字节序问题,如果不使用同一的字节序,发送/接收的数据可能是错误的。网络字节序分为两种:

  • 大端字节序:低地址存放高位数据,高地址存放低位数据
  • 小段字节序:低地址存放低位数据,高地址存放高位数据

在这里插入图片描述

如何确定本机上是大端还是小段,代码测试实例如下:

#include <stdio.h>union {short sval;char cval[sizeof(short)];
} u1;union {int ival;char cval[sizeof(int)];
} u2;int main() {u1.sval = 0x0102;// cval[0] 中存放的是 0x01 则是大端字节序,否则则是小端字节序printf("u1.sval = %#x, u1.cval[0] = %#x, u1.cval[1] = %#x\n", u1.sval, u1.cval[0], u1.cval[1]);u2.ival = 0x01020304;printf("u2.ival = %#x, u2.cval[0] = %#x, u2.cval[1] = %#x, u2.cval[2] = %#x, u2.cval[3] = %#x\n", u2.ival, u2.cval[0], u2.cval[1], u2.cval[2], u2.cval[3]);return 0;
}

在网络传输中使用的是大端字节序,如果机器用的是小端法,则需要进行大小端的转换。一般使用以下 4 个函数:

#include <arpa/inet.h>// 将主机字节序转换为网络字节序
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);// 将网络字节序转换为主机字节序
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

其中 h 表示主机 host,n 表示网络 network,s 表示 shortl 表示 long

socket 编程的 API 函数

socket 函数

socket 函数用来创建一个网络套接字

#include <sys/types.h>
#include <sys/socket.h>/*** @param:*   domain: 协议版本,有 AF_INET 表示 IPV4,AF_INET6 表示 IPV6 等*   type: 协议类型,主要有 SOCK_STREAM 和 SOCK_DGRAM,分别表示 TCP 和 UDP*   protocol: 一般填 0, 表示使用对应类型的默认协议*  @return: 成功返回大于 0 的文件描述符,失败返回 -1*/
int socket(int domain, int type, int protocol);

当调用 socket 函数以后,返回一个文件描述符,内核会提供与该文件描述符相对应的读和写缓冲区,同时还有两个队列,分别是请求连接队列和已连接队列。
在这里插入图片描述

bind 函数

bind 函数将 socket 创建的文件描述符与 IP,port 绑定

#include <sys/types.h>
#include <sys/socket.h>/*** @param:*   sockfd: 调用 socket 函数返回的文件描述符*   addr: 本地服务器的 IP 地址和 PORT*   addrlen: addr 变量的占用的内存大小*  @return: 成功返回 0,失败返回 -1*/
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

sockaddr 是一个保存 IP 和 PORT 的结构体,其原型如下:

struct sockaddr {sa_family_t sa_family;char sa_data[14];
}

由于 sockaddr 在保存地址数据的时候比较繁琐,有了 sockaddr_in 结构,其结构原型如下:

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 */
};

在实际的使用中,使用更多的是 sockaddr_in 结构类型,传参时进行类型转换即可,这两个结构体的大小是一样的。

在这里插入图片描述

listen 函数

listen 函数将套接字由主动改为被动

#include <sys/types.h>
#include <sys/socket.h>/*** @param:*   sockfd: 调用 socket 函数返回的文件描述符*   backlog: 同时请求连接的最大来凝结个数(进入连接队列)*  @return: 成功返回 0,失败返回 -1*/
int listen(int sockfd, int backlog);
accept 函数

accept 函数从连接队列中获取一个连接,如何连接队列中没有连接则会阻塞等待

#include <sys/types.h>
#include <sys/socket.h>/*** @param:*   sockfd: 调用 socket 函数返回的文件描述符*   addr: 传出参数,保存客户端的地址信息*   addrlen: 传入传出参数,addr 变量所占内存空间大小*  @return: 成功返回获取连接客户端的文件描述符,失败返回 -1*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

内核会负责将请求队列中的连接拿到已连接队列中。

connect 函数

connect 函数是主动向指定的 IP 和 PORT 地址发送连接请求。

#include <sys/types.h>
#include <sys/socket.h>/*** @param:*   sockfd: 调用 socket 函数返回的文件描述符*   addr: 服务端的地址信息*   addrlen: addr 变量所占内存空间大小*  @return: 成功返回 0,失败返回 -1*/
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

在发送请求连接前,需要确定服务器的地址信息,其中包括以点分十进制表示的 IP 地址,将其转换成网络字节序的 IP 地址方式使用以下的函数:

#include <arpa/inet.h>/*** @description: 将 IPV4 或 IPV6 的地址从点分十进制的 IP 转换为网络字节序* @param:*   af: AF_INET 或 AF_INET6*   src: 字符串形式的点分十进制的 IP 地址*   dst: 存放转换后的变量的地址*  @return: 成功返回指向 dst 的指针,失败返回 NULL*/
int inet_pton(int af, const char *src, void *dst);/*** @description: 将 IPV4 或 IPV6 的地址从网络字节序转换为点分十进制的 IP* @param:*   af: AF_INET 或 AF_INET6*   src: 网络的整形的 IP 地址*   dst: 转换后的 IP 地址,一般为字符串数组*   size: dst 的长度*  @return: 成功返回指向 dst 的指针,失败返回 NULL*/
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

服务器端和客户端的开发流程

使用 socket 的 API 函数编写服务端和客户端程序的步骤图示

在这里插入图片描述

服务器端的实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>#define BUFFERSIZE 1024int main(int argc, char *argv[]) {if (2 != argc) {fprintf(stderr, "Usage: %s <port>\n", argv[0]);exit(EXIT_FAILURE);}// 创建套接字int sfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sfd) {perror("socket() error");exit(EXIT_FAILURE);}// 绑定 IP 和 PORTstruct sockaddr_in serv_addr;serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(atoi(argv[1]));if (-1 == bind(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {perror("bind() error");close(sfd);exit(EXIT_FAILURE);}// 将套接字由主动态变为被动态if (-1 == listen(sfd, 2)) {close(sfd);perror("listen() error");exit(EXIT_FAILURE);}// 从连接获得一个连接,没有连接则阻塞等待,连接队列取完则退出struct sockaddr_in clnt_addr;socklen_t addr_len = sizeof(clnt_addr);int cfd = accept(sfd, (struct sockaddr *)&clnt_addr, &addr_len);if (-1 == cfd) {close(sfd);perror("accept() error");exit(EXIT_FAILURE);}int rlen;char message[BUFFERSIZE] = {0};// 开始读取和发送数据while (1) {memset(message, 0, BUFFERSIZE);rlen = read(cfd, message, BUFFERSIZE);if (0 == rlen) {printf("client %d is disconnected\n", cfd);break;} else if (0 > rlen) {perror("read() error");break;}printf("READ: %s", message);write(cfd, message, rlen);}close(cfd);close(sfd);return 0;
}
客户端的实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>#define BUFFERSIZE 1024int main(int argc, char *argv[]) {if (3 != argc) {fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);exit(EXIT_FAILURE);}// 创建套接字int cfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == cfd) {perror("socket() error");exit(EXIT_FAILURE);}// 向服务器端发送连接请求struct sockaddr_in clnt_addr;clnt_addr.sin_family = AF_INET;inet_pton(AF_INET, argv[1], &clnt_addr.sin_addr.s_addr);clnt_addr.sin_port = htons(atoi(argv[2]));if (-1 == connect(cfd, (struct sockaddr *)&clnt_addr, sizeof(clnt_addr))) {close(cfd);perror("connect() error");exit(EXIT_FAILURE);}char message[BUFFERSIZE] = {0};while (1) {memset(message, 0, BUFFERSIZE);printf("Please input message(q/Q to quit): ");fgets(message, BUFFERSIZE-1, stdin);if (!strcmp(message, "Q\n") || !strcmp(message, "q\n"))break;int wlen = write(cfd, message, sizeof(message));printf("WRITE: %s", message);int rlen = read(cfd, message, BUFFERSIZE);if (rlen < 0) {perror("read() error");break;}printf("READ: %s", message);}close(cfd);return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单线性回归分析-基于R语言

本题中&#xff0c;在不含截距的简单线性回归中&#xff0c;用零假设对统计量进行假设检验。首先&#xff0c;我们使用下面方法生成预测变量x和响应变量y。 set.seed(1) x <- rnorm(100) y <- 2*xrnorm(100) &#xff08;a&#xff09;不含截距的线性回归模型构建。 &…

计算机网络(九) —— Tcp协议详解

目录 一&#xff0c;关于Tcp协议 二&#xff0c;Tcp报头字段解析 2.0 协议字段图示 2.1 两个老问题 2.2 16位窗口大小 2.3 32位序号和确认序号 2.4 6个标记位 三&#xff0c;Tcp保证可靠性策略 3.1 确认应答机制&#xff08;核心&#xff09; 3.2 超时重传机制 3.3 …

基于开源WQ装备知识图谱的智能问答优化2

基于笔者之前写的博客基础上&#xff1a;https://blog.csdn.net/zhanghan11366/article/details/142139488【基于开源WQ装备知识图谱的智能问答全流程构建】进行优化。新增处理基于特定格式下的WQ文档&#xff0c;抽取文档的WQ属性和关系&#xff0c;并抽取对应WQt图片存储至mi…

位运算(3)_判定字符是否唯一_面试题

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 位运算(3)_判定字符是否唯一_面试题 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目…

c++11~c++20 结构化绑定

结构化帮绑定可以作用于3中类型 一、原生数组类型 结果&#xff1a; 备注&#xff1a;绑定到原生数组所需条件仅仅是要求别名的数量于数组元素的个数一致&#xff0c;这里的x&#xff0c;y&#xff0c;z分别绑定到a[0],a[1],a[2] 二、绑定到结构体和类对象 结果&#xff1a;…

selenium测试框架快速搭建详解

一、介绍 Selenium目前主流的web自动化测试框架&#xff1b;支持多种编程语言Java、pythan、go、js等&#xff1b;selenium 提供一系列的api 供我们使用&#xff0c;因此在web测试时我们要点页面中的某一个按钮&#xff0c;那么我们只需要获取页面&#xff0c;然后根据id或者n…

JQuery基本介绍和使用方法

JQuery基本介绍和使用方法 W3C 标准给我们提供了⼀系列的函数, 让我们可以操作: ⽹⻚内容⽹⻚结构⽹⻚样式 但是原⽣的JavaScript提供的API操作DOM元素时, 代码⽐较繁琐, 冗⻓. 我们可以使⽤JQuery来操作⻚⾯对象. jQuery是⼀个快速、简洁且功能丰富的JavaScript框架, 于20…

uniapp数据缓存

利用uniapp做开发时&#xff0c;缓存数据是及其重要的&#xff0c;下面是同步缓存和异步缓存的使用 同步缓存 在执行同步缓存时会阻塞其他代码的执行 ① uni.setStorageSync(key, data) 设置缓存&#xff0c;如&#xff1a; uni.setStorageSync(name, 张三) ② uni.getSt…

MyBatis的注入问题

对之前文章的补充&#xff1a;MyBatis中的#{}与${}注入问题----原文链接 前言&#xff1a; MyBatis是一个流行的Java持久层框架&#xff0c;用于将对象与数据库中的数据进行映射。然而&#xff0c;如果不当使用&#xff0c;MyBatis也可能受到诸如SQL注入这类的安全问题的影响。…

在传销案件中数据库取证的分步指南

金字塔计划的特点是分层结构&#xff0c;主要由招募新成员的机制驱动。取证部门调查这些方案时&#xff0c;往往依靠数据库记录来分析这种结构。这些记录详细描述了上级和下级之间的关系&#xff0c;使调查人员能够描绘出组织的动态。在本文中&#xff0c;我们将探讨如何利用数…

RuoYi-Vue实现后台管理系统去掉首页/默认跳转动态路由第一个路由

云风网 云风笔记 云风知识库 RuoYi-Vue 是一个 Java EE 企业级快速开发平台&#xff0c;基于SpringBoot、Spring Security、Jwt、Vue的前后端分离的后台管理系统 内置模块如&#xff1a;部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理、代码生成等。在线定…

Windows11系统下SkyWalking环境搭建教程

目录 前言SkyWalking简介SkyWalking下载Agent监控实现启动配置SkyWalking启动Java应用程序启动Elasticsearch安装总结 前言 本文为博主在项目环境搭建时记录的SkyWalking安装流程&#xff0c;希望对大家能够有所帮助&#xff0c;不足之处欢迎批评指正&#x1f91d;&#x1f91…

【YashanDB知识库】GBK库,生僻字插入nvarchar2字段后乱码问题

本文内容来自YashanDB官网&#xff0c;具体内容可见(https://www.yashandb.com/newsinfo/7488287.html?templateId1718516) 问题现象 如下SQL&#xff0c;插入的人名中有两个GBK生僻字“ ”和“ ”&#xff0c;GBK编码中没有这两个字符。 插入后&#xff0c;客户端utf8编码…

华为源NAT技术与目的NAT技术

1&#xff09;源NAT对报文源地址进行转换&#xff0c;分为NAT NO-PAT&#xff0c;NAPT,EASY-IP,三元组NAT&#xff1b; &#xff08;1&#xff09;NAT NO-PAT原理&#xff1a; no-port address translation:非端口地址转换&#xff1a;只转换地址&#xff0c;不转换端口&…

短视频剪辑工具有哪些?推荐4个简单好用的工具

短视频如今充斥着我们的生活&#xff0c;刷短视频已经成了很多人的生活必备。所以掌握短视频剪辑技能是一件很重要的事情&#xff0c;能够为视频创作者带来很多的流量。如果想要学习剪辑的话&#xff0c;可以先从选择一款合适的剪辑工具开始&#xff0c;这几款功能丰富的软件&a…

心理咨询预约管理系统(含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 心理咨询预约管理系统2拥有三个角色&#xff1a; 管理员端 首页 系统近况&#xff08;咨询师和注册来访者数量&#xff0c;预约数量&#xff09; 显示最新的消息、留言和公告&#xff0…

AI驱动TDSQL-C Serverless 数据库技术实战营-与AI的碰撞

目录 一、简介 二、实验介绍 三、结果展示 四、实操指导 4.1 系统设计 4.2 环境搭建&#xff08;手把手教程&#xff09; 4.3 应用构建 4.4 效果展示 4.5 踩坑避雷总结 五、清理资源 5.1 删除TDSQL-C Serverless 5.2 删除 HAI 算力 六、实验总结归纳 一、简介 本…

大模型增量训练--基于transformer制作一个大模型聊天机器人

针对夸夸闲聊数据集&#xff0c;利用UniLM模型进行模型训练及测试&#xff0c;更深入地了解预训练语言模型的使用方法&#xff0c;完成一个生成式闲聊机器人任务。 项目主要结构如下&#xff1a; data 存放数据的文件夹 dirty_word.txt 敏感词数据douban_kuakua_qa.txt 原始语…

k8s上安装prometheus

一、下载对应的kube-prometheus源码 github地址&#xff1a;https://github.com/prometheus-operator/kube-prometheus 根据自己的Kubernetes版本下载对应的Kube-prometheus源码。 kubectl version 我的kubernetes的版本为v1.30.3固下载master分支的源码 1&#xff09;进入…

INTO:Web3世界的“价值引力场”

在Web3的宇宙中&#xff0c;一股强大的引力正在重塑整个数字世界的格局。这股引力&#xff0c;来自一个名为INTO的“超级连接器”。作为Web3社交领域的先锋&#xff0c;INTO正在用一种前所未有的方式重构整个产业链的价值体系。它不再满足于单一领域的创新&#xff0c;而是大胆…