文章目录
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; // 协议族为IPv4
server_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_ANY
int 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操作符来进行动态内存管理?
之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!