Socket编程用到的函数TCP UDP实例

最基本的 Socket 模型

参考这次答应我,一举拿下 I/O 多路复用! (qq.com)

Socket编程详解-CSDN博客

Socket是一种通信机制,通过它可以在不同主机之间进行数据交换。在Socket编程中,有两种常见的通信模式:客户端-服务器模式点对点模式。它基于TCP/IP协议栈,并使用IP地址端口号来标识通信的目标。

Socket  的中文名叫作套接字,欲建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket pair就唯一标识一个连接。因此可以用Socket来描述网络连接的一对一关系。很像弄了一根网线,一头插在客户端,一头插在服务端,然后进行通信。“IP地址+端口号”就对应一个socket。

在网络通信中,套接字一定是成对出现的。一端的发送缓冲区对应对端的接收缓冲区。我们使用同一个文件描述符索发送缓冲区和接收缓冲区。

服务端首先调用socket()函数,创建网络协议为 IPv4,以及传输协议为 TCP 的 Socket ,接着调用bind()函数,给这个 Socket 绑定一个 IP 地址和端口,绑定这两个的目的是什么?

  • 绑定端口的目的:当内核收到 TCP 报文,通过 TCP 头里面的端口号,来找到我们的应用程序,然后把数据传递给我们。

  • 绑定 IP 地址的目的:一台机器是可以有多个网卡的,每个网卡都有对应的 IP 地址,当绑定一个网卡时,内核在收到该网卡上的包,才会发给我们;

绑定完 IP 地址和端口后,就可以调用listen()函数进行监听,此时对应 TCP 状态图中的 listen,如果我们要判定服务器中一个网络程序有没有启动,可以通过 netstate 命令查看对应的端口号是否有被监听。

服务端进入了监听状态后,通过调用accept()函数,来从内核获取客户端的连接,如果没有客户端连接,则会阻塞等待客户端连接的到来。

那客户端是怎么发起连接的呢?客户端在创建好 Socket 后,调用connect()函数发起连接,该函数的参数要指明服务端的 IP 地址和端口号,然后万众期待的 TCP 三次握手就开始了。

在  TCP 连接的过程中,服务器的内核实际上为每个 Socket 维护了两个队列:

  • 一个是还没完全建立连接的队列,称为 TCP 半连接队列,这个队列都是没有完成三次握手的连接,此时服务端处于syn_rcvd的状态;

  • 一个是一件建立连接的队列,称为 TCP 全连接队列,这个队列都是完成了三次握手的连接,此时服务端处于established状态;

当 TCP 全连接队列不为空后,服务端的accept()函数,就会从内核中的 TCP 全连接队列里拿出一个已经完成连接的  Socket 返回应用程序,后续数据传输都用这个 Socket。

注意,监听的 Socket 和真正用来传数据的 Socket 是两个:

  • 一个叫作监听 Socket

  • 一个叫作已连接 Socket

连接建立后,客户端和服务端就开始相互传输数据了,双方都可以通过read()write()函数来读写数据。

至此, TCP 协议的 Socket 程序的调用过程就结束了

基于 Linux 一切皆文件的理念,在内核中 Socket 也是以「文件」的形式存在的,也是有对应的文件描述符(内核可以通过文件描述符找到对应打开的文件)

相关知识

参考CC++ socket网络编程扫盲篇_c++端口号的数据类型-CSDN博客

大小端存储

大小端是针对非单字节数据的存取,比如short型,int型等。大端存储是将数据的高位存储在内存的低地址处,小端存储是将数据的低位存储在内存的低地址处。

为什么会有大小端?

        简单点说就是硬件厂商各有所好,并没有统一的约定制作制作哪一个,大端的优势在于第一个字节就是高位,很容易判断正负性。小端的优势在于第一个字节是低位,最后一个字节是高位,可以依次取出相应的字节进行运算,并且最终会把符号位刷新,这样运算起来更高效。

       内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分。网络数据流同样有大端小端之分,那么如何定义网络数据流的地址呢?发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存,因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。

TCP/IP协议规定:网络数据流应采用大端字节序,即低地址高字节。

IP地址(IP Address)

计算机分布在世界各地,要想和它们通信,必须要知道确切的位置。确定计算机位置的方式有多种,IP 地址是最常用的,例如,114.114.114.114 是国内第一个、全球第三个开放的 DNS 服务地址,127.0.0.1 是本机地址。

其实,我们的计算机并不知道 IP 地址对应的地理位置,当要通信时,只是将 IP 地址封装到要发送的数据包中,交给路由器去处理。路由器有非常智能和高效的算法,很快就会找到目标计算机,并将数据包传递给它,完成一次单向通信。

目前大部分软件使用 IPv4 地址,但 IPv6 也正在被人们接受,尤其是在教育网中,已经大量使用。

端口(Port)

有了 IP 地址,虽然可以找到目标计算机,但仍然不能进行通信。一台计算机可以同时提供多种网络服务,例如Web服务、FTP服务(文件传输服务)、SMTP服务(邮箱服务)等,仅有 IP 地址,计算机虽然可以正确接收到数据包,但是却不知道要将数据包交给哪个网络程序来处理,所以通信失败。

为了区分不同的网络程序,计算机会为每个网络程序分配一个独一无二的端口号(Port Number),例如,Web服务的端口号是 80,FTP 服务的端口号是 21,SMTP 服务的端口号是 25。

端口(Port)是一个虚拟的、逻辑上的概念。可以将端口理解为一道门,数据通过这道门流入流出,每道门有不同的编号,就是端口号。如下图所示:

协议(Protocol)

协议(Protocol)就是网络通信的约定,通信的双方必须都遵守才能正常收发数据。协议有很多种,例如 TCP、UDP、IP 等,通信的双方必须使用同一协议才能通信。协议是一种规范,由计算机组织制定,规定了很多细节,例如,如何建立连接,如何相互识别等。

协议仅仅是一种规范,必须由计算机软件来实现。例如 IP 协议规定了如何找到目标计算机,那么各个开发商在开发自己的软件时就必须遵守该协议,不能另起炉灶。

所谓协议族(Protocol Family),就是一组协议(多个协议)的统称。最常用的是 TCP/IP 协议族,它包含了 TCP、IP、UDP、Telnet、FTP、SMTP 等上百个互为关联的协议,由于 TCP、IP 是两种常用的底层协议,所以把它们统称为 TCP/IP 协议族。

数据传输方式

计算机之间有很多数据传输方式,各有优缺点,常用的有两种:SOCK_STREAM(使用TCP协议)SOCK_DGRAM(使用UDP协议)

SOCK_STREAM 表示面向连接的数据传输方式。数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送,但效率相对较慢。常见的 http 协议就使用 SOCK_STREAM 传输数据,因为要确保数据的正确性,否则网页不能正常解析。
SOCK_DGRAM 表示无连接的数据传输方式。计算机只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。也就是说,数据错了就错了,无法重传。因为 SOCK_DGRAM 所做的校验工作少,所以效率比 SOCK_STREAM 高。

QQ 视频聊天和语音聊天就使用 SOCK_DGRAM 传输数据,因为首先要保证通信的效率,尽量减小延迟,而数据的正确性是次要的,即使丢失很小的一部分数据,视频和音频也可以正常解析,最多出现噪点或杂音,不会对通信质量有实质的影响。

注意:SOCK_DGRAM 没有想象中的糟糕,不会频繁的丢失数据,数据错误只是小概率事件。

有可能多种协议使用同一种数据传输方式,所以在 socket 编程中,需要同时指明数据传输方式和协议。

综上所述:IP地址和端口能够在广袤的互联网中定位到要通信的程序,协议和数据传输方式规定了如何传输数据,有了这些,两台计算机就可以通信了。

Socket编程基本步骤

参考Socket编程详解:从基本概念到实例应用(TCP|UDP C语言实例详解)-CSDN博客

常用函数的原型和参数用法详解:

要使用Socket函数之前要先包含两个头文件

#include <sys/types.h>

#include <socket.h>

1.socket()函数

int socket(int domain, int type, int protocol);
domain:地址族,通常为AF_INET(IPv4)或AF_INET6(IPv6)。
type:套接字类型,可以是SOCK_STREAM(TCP)或SOCK_DGRAM(UDP)。
protocol:协议,通常为0,表示自动选择合适的协议。

2.bind()函数

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:套接字描述符。
addr:指向本地地址结构体的指针。
addrlen:地址结构体的长度。

3.listen()函数

int listen(int sockfd, int backlog);
sockfd:套接字描述符。
backlog:待连接队列的最大长度。

4.accept()函数

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd:套接字描述符。
addr:指向客户端地址结构体的指针,用于存储客户端的地址信息。
addrlen:指向地址结构体长度的指针。

5.connect()函数

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:套接字描述符。
addr:指向目标地址结构体的指针。
addrlen:地址结构体的长度。

6.send()函数

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
sockfd:套接字描述符。
buf:指向要发送数据的缓冲区的指针。
len:要发送的数据的长度。
flags:发送标志,通常为0。

7.recv()函数

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
sockfd:套接字描述符。
buf:指向接收数据的缓冲区的指针。
len:要接收的数据的最大长度。
flags:接收标志,通常为0。

8.sendto()函数

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
sockfd:套接字描述符。
buf:指向要发送数据的缓冲区的指针。
len:要发送的数据的长度。
flags:发送标志,通常为0。
dest_addr:指向目标地址结构体的指针。
addrlen:目标地址结构体的长度。

9.recvfrom()函数

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
sockfd:套接字描述符。
buf:指向接收数据的缓冲区的指针。
len:要接收的数据的最大长度。
flags:接收标志,通常为0。
src_addr:指向源地址结构体的指针,用于存储源地址信息。
addrlen:指向地址结构体长度的指针。

10.close()函数

int close(int sockfd);
sockfd:套接字描述符。

通过使用这些函数,可以实现TCP和UDP通信的服务器端和客户端程序。TCP提供可靠的、面向连接的通信,适用于需要确保数据可靠性和顺序性的场景,而UDP提供无连接的通信,适用于实时性要求较高但可靠性要求较低的场景。

TCP开发流程:

1.服务器端:

  • 创建套接字:int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
  • 绑定地址:struct sockaddr_in serverAddress; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); serverAddress.sin_addr.s_addr = INADDR_ANY; bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
  • 监听连接:listen(serverSocket, backlog);
  • 接受连接:struct sockaddr_in clientAddress; int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, sizeof(clientAddress));
  • 发送和接收数据:send(clientSocket, buffer, size, 0); recv(clientSocket, buffer, size, 0);
  • 关闭连接:close(clientSocket); close(serverSocket);

2.客户端:

  • 创建套接字:int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
  • 连接服务器:struct sockaddr_in serverAddress; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); serverAddress.sin_addr.s_addr = inet_addr(serverIP); connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
  • 发送和接收数据:send(clientSocket, buffer, size, 0); recv(clientSocket, buffer, size, 0);
  • 关闭连接:close(clientSocket);

UDP开发流程:

1.服务器端:

  • 创建套接字:int serverSocket = socket(AF_INET, SOCK_DGRAM, 0);
  • 绑定地址:struct sockaddr_in serverAddress; serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); serverAddress.sin_addr.s_addr = INADDR_ANY; bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
  • 接收和发送数据:recvfrom(serverSocket, buffer, size, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress)); sendto(serverSocket, buffer, size, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress));
  • 关闭套接字:close(serverSocket);

2.客户端:

  • 创建套接字:int clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
  • 发送和接收数据:sendto(clientSocket, buffer, size, 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress)); recvfrom(clientSocket, buffer, size, 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
  • 关闭套接字:close(clientSocket);

Socket编程实例 

以下是使用C语言通过Socket实现TCP和UDP通信的服务端和客户端通信程序的示例:

TCP通信示例:

服务端(server.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024int main() {int serverSocket, clientSocket;struct sockaddr_in serverAddr, clientAddr;socklen_t clientAddrLen;char buffer[BUFFER_SIZE];// 创建服务端套接字serverSocket = socket(AF_INET, SOCK_STREAM, 0);if (serverSocket == -1) {perror("Failed to create socket");exit(EXIT_FAILURE);}// 设置服务器地址信息memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(SERVER_PORT);serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);// 绑定套接字到指定地址和端口if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {perror("Failed to bind socket");exit(EXIT_FAILURE);}// 监听连接请求if (listen(serverSocket, 5) == -1) {perror("Failed to listen");exit(EXIT_FAILURE);}printf("Server listening on port %d...\n", SERVER_PORT);// 接受客户端连接clientAddrLen = sizeof(clientAddr);clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &clientAddrLen);if (clientSocket == -1) {perror("Failed to accept client connection");exit(EXIT_FAILURE);}printf("Client connected: %s\n", inet_ntoa(clientAddr.sin_addr));// 接收数据memset(buffer, 0, sizeof(buffer));if (recv(clientSocket, buffer, BUFFER_SIZE, 0) == -1) {perror("Failed to receive data");exit(EXIT_FAILURE);}printf("Client message: %s\n", buffer);// 发送响应strcpy(buffer, "Hello, Client!");if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {perror("Failed to send data");exit(EXIT_FAILURE);}// 关闭套接字close(clientSocket);close(serverSocket);return 0;
}

客户端(client.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024int main() {int clientSocket;struct sockaddr_in serverAddr;char buffer[BUFFER_SIZE];// 创建客户端套接字clientSocket = socket(AF_INET, SOCK_STREAM, 0);if (clientSocket == -1) {perror("Failed to create socket");exit(EXIT_FAILURE);}// 设置服务器地址信息memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(SERVER_PORT);if (inet_pton(AF_INET, SERVER_IP, &(serverAddr.sin_addr)) <=0) {perror("Failed to set server IP");exit(EXIT_FAILURE);}// 连接到服务器if (connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {perror("Failed to connect to server");exit(EXIT_FAILURE);}printf("Connected to server %s:%d\n", SERVER_IP, SERVER_PORT);// 发送数据strcpy(buffer, "Hello, Server!");if (send(clientSocket, buffer, strlen(buffer), 0) == -1) {perror("Failed to send data");exit(EXIT_FAILURE);}// 接收响应memset(buffer, 0, sizeof(buffer));if (recv(clientSocket, buffer, BUFFER_SIZE, 0) == -1) {perror("Failed to receive data");exit(EXIT_FAILURE);}printf("Server response: %s\n", buffer);// 关闭套接字close(clientSocket);return 0;
}

UDP通信示例:

服务端(server.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024int main() {int serverSocket;struct sockaddr_in serverAddr, clientAddr;socklen_t clientAddrLen;char buffer[BUFFER_SIZE];// 创建服务端套接字serverSocket = socket(AF_INET, SOCK_DGRAM, 0);if (serverSocket == -1) {perror("Failed to create socket");exit(EXIT_FAILURE);}// 设置服务器地址信息memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(SERVER_PORT);serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);// 绑定套接字到指定地址和端口if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {perror("Failed to bind socket");exit(EXIT_FAILURE);}printf("Server listening on port %d...\n", SERVER_PORT);// 接收数据clientAddrLen = sizeof(clientAddr);memset(buffer, 0, sizeof(buffer));if (recvfrom(serverSocket, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&clientAddr, &clientAddrLen) == -1) {perror("Failed to receive data");exit(EXIT_FAILURE);}printf("Client message: %s\n", buffer);// 发送响应strcpy(buffer, "Hello, Client!");if (sendto(serverSocket, buffer, strlen(buffer), 0, (struct sockaddr *)&clientAddr, clientAddrLen) == -1) {perror("Failed to send data");exit(EXIT_FAILURE);}// 关闭套接字close(serverSocket);return 0;
}

客户端(client.c):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080
#define BUFFER_SIZE 1024int main() {int clientSocket;struct sockaddr_in serverAddr;char buffer[BUFFER_SIZE];// 创建客户端套接字clientSocket = socket(AF_INET, SOCK_DGRAM, 0);if (clientSocket == -1) {perror("Failed to create socket");exit(EXIT_FAILURE);}// 设置服务器地址信息memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(SERVER_PORT);if (inet_pton(AF_INET, SERVER_IP, &(serverAddr.sin_addr)) <= 0) {perror("Failed to set server IP");exit(EXIT_FAILURE);}printf("Connected to server %s:%d\n", SERVER_IP, SERVER_PORT);// 发送数据strcpy(buffer, "Hello, Server!");if (sendto(clientSocket, buffer, strlen(buffer), 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {perror("Failed to send data");exit(EXIT_FAILURE);}// 接收响应memset(buffer, 0, sizeof(buffer));if (recvfrom(clientSocket, buffer, BUFFER_SIZE, 0, NULL, NULL) == -1) {perror("Failed to receive data");exit(EXIT_FAILURE);}printf("Server response: %s\n", buffer);// 关闭套接字close(clientSocket);return 0;
}

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

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

相关文章

PIP换源的全面指南

##概述 在Python的世界里&#xff0c;pip是不可或缺的包管理工具&#xff0c;它帮助开发者安装和管理Python软件包。然而&#xff0c;由于网络条件或服务器位置等因素&#xff0c;直接使用默认的pip源有时会遇到下载速度慢或者连接不稳定的问题。这时&#xff0c;更换pip源到一…

在Linux操作系统中去修复/etc/fstab文件引起的系统故障。

如果/etcfstab文件中发生错误&#xff0c;有可能导致系统无法正常启动。 比如&#xff1a;系统里的一块磁盘被删除&#xff0c;但是/etc/fstab中关于这块磁盘的信息依然被保存在文件/etc/fstab中。 主要看倒数后两行&#xff0c;系统提示&#xff0c;敲ctrlD或者是直接输入密码…

Linux muduo 网络库

主要记录示意图和知识点框架&#xff1a; 1、阻塞、非阻塞、同步、异步 在处理IO的时候&#xff0c;阻塞和非阻塞都是同步IO&#xff0c;只有使用了特殊的API才是异步IO。 2、五种IO模型&#xff1a; 阻塞、非阻塞、IO复用、信号驱动、异步IO 3、muduo网络库 muduo网络库给用…

【Java】垃圾回收学习笔记(一):Root Search 根可达算法+垃圾回收的起点

文章目录 1. 引用计数法优点缺点 2. 可达性分析 Root Search2.1 那些对象是GC Roots2.2 引用的分类2.3 回收方法区 3. 实现细节3.1 GC的起点&#xff1a;节点枚举OopMap&#xff1a;帮助高效的根节点枚举 3.2 何时开始GC&#xff1a;安全点与安全区域如何选取安全点如何让程序进…

rocketmq-console可视化界面功能说明

rocketmq-console可视化界面功能说明 登录界面OPS(运维)Dashboard(驾驶舱)Cluster(集群)Topic(主题)Consumer(消费者)Producer(生产者)Message(消息)MessageTrace(消息轨迹) rocketmq-console是rocketmq的一款可视化工具&#xff0c;提供了mq的使用详情等功能。 本章针对于rock…

玫瑰千层烤饼:味蕾的芬芳盛宴

在美食的缤纷世界里&#xff0c;有一种独特的存在&#xff0c;它融合了玫瑰的芬芳与烤饼的酥脆&#xff0c;那便是令人陶醉的甘肃美食玫瑰千层烤饼。食家巷玫瑰千层烤饼&#xff0c;宛如一件精心雕琢的艺术品。每一层薄如纸张的面皮&#xff0c;都承载着制作者的细腻与用心。层…

【qt】TCP 服务端怎么收到信息?

上一节,我已经讲了,TCP的监听,是基于上一节的,不知道的可以看看. 当我们的TCP 服务器 有 客户端请求连接的时候,会发出一个信号newConnection(). 在TCP服务端与客户端的通信中,我们需要使用到套接字 QTcpSocket类. 套接字相当于是网络通信的接口,服务段和客户端都要通过它进行通…

Gitlab Fork Workflow(协作工作流)

Gitlab Fork WorkFlow&#xff08;协作工作流&#xff09; Fork WorkFlow用于团队间的协作开发。在开发过程中&#xff0c;我们都需要将最新修改的代码合并到代码库上&#xff0c;在代码合并之前&#xff0c;为了保证代码符合上传要求&#xff08;符合需求、代码规范等&#xf…

如何在应用运行时定期监控内存使用情况

如何在应用运行时定期监控内存使用情况 在 iOS 应用开发中&#xff0c;实时监控内存使用情况对于优化性能和排查内存泄漏等问题非常重要。本文将介绍如何在应用运行时定期监控内存使用情况&#xff0c;使用 Swift 编写代码并结合必要的工具和库。 1. 创建桥接头文件 首先&…

vue学习笔记之组件传值

说起组件传值&#xff0c;首先要介绍再vue中什么是组件。 组件&#xff08;Component&#xff09;&#xff0c;是vue中很强大的一个功能&#xff0c;可以将一些可重用的代码进行重用。所有的vue组件同时也是vue实例&#xff0c;可以接受使用相同的选项对象和提供相同的生命周期…

集合复习(java)

文章目录 Collection 接口Collection结构图Collection接口中的方法Iterator 与 Iterable 接口Collection集合遍历方式迭代器遍历增强 for 遍历 List&#xff08;线性表&#xff09;List特有方法ArrayList&#xff08;可变数组&#xff09;ArrayList 底层原理ArrayList 底层原理…

JAVA集合框架、CAS、AQS

目录 一、java 的集合框架有哪些? 二、说-下 ArrayList 和 LinkedList? 三、HashSet和TreeSet的区别? 四、HashMap 的数据结构是什么? 五、CAS机制 六、AQS理解 一、java 的集合框架有哪些? Collection 是 Java 集合框架中的一个根接口&#xff0c;位于 java.util 包中。它…

【SVN的使用-源代码管理工具-命令行的使用 Objective-C语言】

一、接下来,我们来说一个终端的命令行的使用, 1.我们说,你的电脑里边呢,有终端, 在Mac里边,你想新建一个txt,应该怎么写,对,打开文本编辑, 打开这个东西,写点儿东西,然后保存一下,保存的时候,你还要去选择格式, 现在,如果我们用命令行,可以更方便一些, 2.首…

【基于R语言群体遗传学】-10-适应性与正选择

在之前的博客中&#xff0c;我们学习了哈代温伯格模型&#xff0c;学习了Fisher模型&#xff0c;学习了遗传漂变与变异的模型&#xff0c;没有看过之前内容的朋友可以先看一下之前的文章&#xff1a; 群体遗传学_tRNA做科研的博客-CSDN博客 一些新名词 &#xff08;1&#xf…

MySQL 中的 DDL、DML、DQL 和 DCL

文章目录 1. 数据定义语言&#xff08;DDL&#xff09;2. 数据操作语言&#xff08;DML&#xff09;3. 数据查询语言&#xff08;DQL&#xff09;4. 数据控制语言&#xff08;DCL&#xff09;总结 在 MySQL 数据库管理系统中&#xff0c;SQL 语句可以根据其功能分为不同的类别&…

RAG 案框架(Qanything、RAGFlow、FastGPT、智谱RAG)对比

各家的技术方案 有道的QAnything 亮点在&#xff1a;rerank RAGFLow 亮点在&#xff1a;数据处理index 智谱AI 亮点在文档解析、切片、query改写及recall模型的微调 FastGPT 优点&#xff1a;灵活性更高 下面分别按照模块比较各框架的却别 功能模块QAnythingRAGFLowFastG…

TP8/6 子域名绑定应用

原www.xxx.com/admin改为admincms.xxx.com config/app.php 官方文档&#xff1a;ThinkPHP官方手册

赋值运算符重载和const成员函数和 const函数

文章目录 1.运算符重载(1)(2)运算符重载的语法&#xff1a;(3)运算符重载的注意事项&#xff1a;(4)前置和后置重载区别 2.const成员函数3.取地址及const取地址操作符重载4.总结 1.运算符重载 (1) 我们知道内置类型(整形&#xff0c;字符型&#xff0c;浮点型…)可以进行一系…

2024-07-05 base SAS programming学习笔记9(variables)

1.在数据集增加累加变量值&#xff08;SUM&#xff09; 求和语句(SUM STATEMENT)&#xff1a;variableexpression variable是累积求和的变量名&#xff0c;为数值型&#xff0c;默认初始值为0&#xff1b;该variable值则会保留到一个观测 当expression有缺失值&#xff0c;在求…

【项目管理】常见的敏捷实践:Scrum框架

【项目管理】常见的敏捷实践&#xff1a;Scrum框架 精益、敏捷与Scrum框架Scrum框架实践Sprint&#xff08;冲刺&#xff09;Scrum角色Scrum工件Scrum会议 精益、敏捷与Scrum框架 敏捷与精益思想、看板、Scrum等概念的关系如下图所示&#xff1a; Lean 精益 Kanban 看板 Ag…