C++高频知识点(二)
文章目录
- 6. UDP和TCP的区别是什么?
- TCP 服务器端示例:
- TCP 客户端示例:
- UDP 服务器端示例:
- UDP 客户端示例:
- 7. 谈谈对ARM架构的理解?
- 8. explicit用在哪里?有什么作用?
- 9. 解释堆与栈之间的区别
- 10. C++中动态内存分配是如何工作的?如何使用new和delete操作符来进行动态内存管理?
6. UDP和TCP的区别是什么?
UDP(User Datagram Protocol)和TCP(Transmission Control Protocol)是两种不同的传输层协议,它们在网络通信中具有不同的特点和用途。
以下是它们之间的主要区别:
总的来说,TCP 提供了稳定可靠的数据传输机制,适用于对数据可靠性要求较高的场景;而 UDP 则提供了更快速的数据传输方式,适用于对实时性要求较高的场景。在选择 TCP 还是 UDP 时,需要根据具体的应用需求来进行权衡。
TCP 服务器端示例:
socket() 创建套接字|
bind() 绑定地址端口|
listen() 监听连接|
accept() 等待客户端连接(阻塞)|
recv() 接收客户端数据|
输出数据|
close() 关闭套接字
#include <iostream> // 标准输入输出流
#include <unistd.h> // UNIX标准函数,如close()
#include <sys/socket.h> // socket相关函数定义
#include <netinet/in.h> // sockaddr_in结构体定义(IPv4地址结构)int main() {// 步骤1: 创建套接字(socket):int server_fd = socket(AF_INET, SOCK_STREAM, 0);// 步骤2: 检查套接字是否创建成功:if (server_fd == -1) {std::cerr << "Error: Failed to create socket." << std::endl;return 1;}// 步骤3: 定义并初始化地址结构体 sockaddr_in:struct sockaddr_in server_addr;server_addr.sin_family = AF_INET; // 使用IPv4地址族server_addr.sin_addr.s_addr = INADDR_ANY; // 绑定到所有本地IP地址(0.0.0.0)server_addr.sin_port = htons(8888); // 设置端口号为8888(网络字节序)// 步骤4: 绑定套接字到指定的地址和端口:if (bind(server_fd, reinterpret_cast<struct sockaddr*>(&server_addr), sizeof(server_addr)) == -1) {std::cerr << "Error: Failed to bind socket." << std::endl;close(server_fd);return 1;}// 步骤5: 开始监听客户端连接请求:if (listen(server_fd, SOMAXCONN) == -1) {std::cerr << "Error: Failed to listen on socket." << std::endl;close(server_fd);return 1;}// 步骤6: 接受客户端的连接请求:struct sockaddr_in client_addr;socklen_t client_addr_len = sizeof(client_addr);int client_fd = accept(server_fd, reinterpret_cast<struct sockaddr*>(&client_addr), &client_addr_len);// 步骤7: 检查客户端连接是否成功:if (client_fd == -1) {std::cerr << "Error: Failed to accept client connection." << std::endl;close(server_fd);return 1;}// 步骤8: 从客户端接收数据:char buffer[1024];ssize_t num_bytes = recv(client_fd, buffer, sizeof(buffer), 0);// 步骤9: 检查数据接收是否成功:if (num_bytes == -1) {std::cerr << "Error: Failed to receive data from client." << std::endl;close(client_fd);close(server_fd);return 1;}// 步骤10: 打印接收到的消息:std::cout << "Received message from client: " << std::string(buffer, num_bytes) << std::endl;// 步骤11: 关闭客户端和服务端套接字:close(client_fd); // 关闭客户端连接套接字close(server_fd); // 关闭服务端监听套接字return 0;
}
TCP 客户端示例:
创建socket|
设置服务器地址(IP、端口)|
连接服务器 (connect)|
发送数据 (send)|
关闭套接字 (close)
#include <iostream> // 用于标准输入输出
#include <unistd.h> // close() 等系统调用函数
#include <sys/socket.h> // socket(), connect(), send()
#include <netinet/in.h> // sockaddr_in, htons()
#include <arpa/inet.h> // inet_pton(),转换IP地址
#include <cstring> // strlen()int main() {// 创建套接字(IPv4协议,TCP连接)int client_fd = socket(AF_INET, SOCK_STREAM, 0);if (client_fd == -1) {std::cerr << "Error: Failed to create socket." << std::endl;return 1;}// 设置服务器地址与连接:struct sockaddr_in server_addr; // IPv4地址结构server_addr.sin_family = AF_INET; // 协议族为IPv4server_addr.sin_port = htons(8888); // 服务器端口,需转为网络字节序inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); // 设置服务器IP地址// 发起连接请求到服务器。if (connect(client_fd, reinterpret_cast<struct sockaddr*>(&server_addr), sizeof(server_addr)) == -1) {std::cerr << "Error: Failed to connect to server." << std::endl;close(client_fd);return 1;}// 发送数据:const char* message = "Hello, TCP server!";ssize_t num_bytes = send(client_fd, message, strlen(message), 0);if (num_bytes == -1) {std::cerr << "Error: Failed to send data to server." << std::endl;close(client_fd);return 1;}std::cout << "Sent message to server: " << message << std::endl;// 关闭连接:close(client_fd); // 关闭套接字,断开与服务器的连接return 0; // 程序正常退出
}
UDP 服务器端示例:
创建套接字(socket)|
绑定IP和端口(bind)|
等待客户端数据(recvfrom 阻塞)|
收到数据后打印|
关闭套接字并退出
#include <iostream> // 控制台输入输出
#include <unistd.h> // close()
#include <sys/socket.h> // socket(), bind(), recvfrom()
#include <netinet/in.h> // sockaddr_in, htons(), INADDR_ANYint main() {// 创建UDP套接字:int server_fd = socket(AF_INET, SOCK_DGRAM, 0);if (server_fd == -1) {std::cerr << "Error: Failed to create socket." << std::endl;return 1;}// 绑定IP地址和端口:struct sockaddr_in server_addr;server_addr.sin_family = AF_INET; // 使用IPv4协议server_addr.sin_addr.s_addr = INADDR_ANY; // 绑定本地所有网络接口server_addr.sin_port = htons(8888); // 使用8888端口,网络字节序// 接收客户端的数据:char buffer[1024]; // 接收缓冲区struct sockaddr_in client_addr; // 存储客户端地址socklen_t client_addr_len = sizeof(client_addr); // 地址结构长度ssize_t num_bytes = recvfrom(server_fd, buffer, sizeof(buffer), 0,reinterpret_cast<struct sockaddr*>(&client_addr),&client_addr_len);if (num_bytes == -1) {std::cerr << "Error: Failed to receive data from client." << std::endl;close(server_fd);return 1;}// 打印接收到的数据:std::cout << "Received message from client: " << std::string(buffer, num_bytes) << std::endl;// 关闭套接字:close(server_fd); // 关闭服务端套接字return 0; // 程序正常退出
}
UDP 客户端示例:
创建UDP套接字(socket)|
准备目标服务器地址(IP与端口)|
发送消息数据报(sendto)|
关闭套接字(close)
#include <iostream> // 控制台输入输出
#include <unistd.h> // close()
#include <sys/socket.h> // socket(), sendto()
#include <netinet/in.h> // sockaddr_in, htons()
#include <arpa/inet.h> // inet_pton()
#include <cstring> // strlen()int main() {// 1. 创建UDP套接字:int client_fd = socket(AF_INET, SOCK_DGRAM, 0);if (client_fd == -1) {std::cerr << "Error: Failed to create socket." << std::endl;return 1;}// 2. 设置目标服务器地址:struct sockaddr_in server_addr;server_addr.sin_family = AF_INET; // IPv4协议族server_addr.sin_port = htons(8888); // 服务器端口号 (转换成网络字节序)inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); // 设置服务器IP地址// 3. 发送数据报(UDP报文):const char* message = "Hello, UDP server!";ssize_t num_bytes = sendto(client_fd, message, strlen(message), 0, reinterpret_cast<struct sockaddr*>(&server_addr), sizeof(server_addr));if (num_bytes == -1) {std::cerr << "Error: Failed to send data to server." << std::endl;close(client_fd);return 1;}// 4. 确认消息发送成功:std::cout << "Sent message to server: " << message << std::endl;// 5. 关闭套接字:close(client_fd); // 关闭UDP套接字,释放资源return 0; // 程序正常退出
}
7. 谈谈对ARM架构的理解?
ARM架构的特点包括低功耗、高性能、小体积等,这使得它在移动设备市场上占据了主导地位。此外,ARM架构的处理器设计也非常灵活,可以根据不同的应用需求进行定制和优化
8. explicit用在哪里?有什么作用?
class Foo
{
public: explicit Foo(int x) : data(x) {}
private: int data;
}; void SomeFunction(Foo fooObj)
{ //...
} int main()
{ // Foo fooObj = 42; // 这行会导致编译错误,因为构造函数被声明为 explicit Foo fooObj(42); // 正确的创建方式 SomeFunction(Foo(42)); // 在调用函数时也需要显式创建对象 // SomeFunction(42); // 这行会导致编译错误,因为构造函数被声明为 explicit,不能隐式转换 return 0;
}
在上面的例子中,如果我们将构造函数声明为explicit,那么就不能通过Foo fooObj = 42;这样的隐式转换来创建对象,而必须显式地调用构造函数。同样地,在调用需要Foo类型参数的函数时,也不能直接传入一个int类型的参数,而必须显式地创建一个Foo对象。这样可以避免因为隐式转换而导致的错误。
9. 解释堆与栈之间的区别
10. C++中动态内存分配是如何工作的?如何使用new和delete操作符来进行动态内存管理?
之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!