c++ linux recv的概念和使用案例(服务端和客户端都有)
recv
函数是用于接收数据的socket函数,在C++ Linux环境中扮演着关键角色。其原型如下:
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数说明:
sockfd
: socket描述符,标识要接收数据的socket。buf
: 指向用于存储接收数据的缓冲区的指针。len
: 缓冲区的长度,指定最多可以接收的字节数。flags
: 接收标志,用于控制接收行为,常用的标志包括:MSG_PEEK
: 查看数据而不移除它们。MSG_OOB
: 接收带外数据。MSG_WAITALL
: 等待直到接收完指定数量的数据或发生错误。
返回值:
- 成功时返回实际接收的字节数。
- 返回-1表示发生错误。
- 返回0表示对方关闭了连接。
使用案例:
以下是服务端和客户端使用recv
函数的示例代码。
服务器端代码:
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <string>
#include <csignal>
#include <thread>
#include <vector>
std::vector<std::thread> threads;
// 信号处理函数
void signal_handler(int sig) {
std::cout << "Server shutting down..." << std::endl;
close(sockfd);
// 等待所有线程完成
for (auto &t : threads) {
if (t.joinable()) {
t.join();
}
}
exit(0);
}
// 处理客户端连接的函数
void handle_client(int client_sock) {
std::string buffer;
buffer.resize(1024);
ssize_t bytes_received = recv(client_sock, &buffer[0], buffer.size(), 0);
if (bytes_received < 0) {
std::cerr << "Error receiving data" << std::endl;
} else if (bytes_received == 0) {
std::cout << "Client disconnected" << std::endl;
} else {
buffer.resize(bytes_received);
std::cout << "Received from client: " << buffer << std::endl;
// 发送响应
const char *response = "Hello, Client!";
ssize_t bytes_sent = send(client_sock, response, strlen(response), 0);
if (bytes_sent < 0) {
std::cerr << "Error sending data" << std::endl;
}
}
// 关闭连接
close(client_sock);
}
int main() {
// 注册信号处理函数
std::signal(SIGINT, signal_handler);
// 创建socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
std::cerr << "Error creating socket" << std::endl;
return -1;
}
// 绑定socket到端口8080
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
std::cerr << "Error binding socket" << std::endl;
close(sockfd);
return -1;
}
// 监听连接,最大连接数为5
if (listen(sockfd, 5) < 0) {
std::cerr << "Error listening on socket" << std::endl;
close(sockfd);
return -1;
}
std::cout << "Server listening on port 8080..." << std::endl;
while (true) {
// 接受连接
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_sock = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
if (client_sock < 0) {
std::cerr << "Error accepting connection" << std::endl;
continue;
}
std::cout << "Client connected" << std::endl;
// 创建线程处理客户端连接
threads.emplace_back(handle_client, client_sock);
threads.back().detach();
}
// 关闭socket
close(sockfd);
return 0;
}
客户端代码:
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
#include <string>
#include <csignal>
// 信号处理函数
void signal_handler(int sig) {
std::cout << "Client shutting down..." << std::endl;
close(sockfd);
exit(0);
}
int main() {
// 注册信号处理函数
std::signal(SIGINT, signal_handler);
// 创建socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
std::cerr << "Error creating socket" << std::endl;
return -1;
}
// 连接到服务器
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
std::cerr << "Error connecting to server" << std::endl;
close(sockfd);
return -1;
}
std::cout << "Connected to server" << std::endl;
// 发送数据
const char *message = "Hello, Server!";
ssize_t bytes_sent = send(sockfd, message, strlen(message), 0);
if (bytes_sent < 0) {
std::cerr << "Error sending data" << std::endl;
}
// 接收响应
std::string buffer;
buffer.resize(1024);
ssize_t bytes_received = recv(sockfd, &buffer[0], buffer.size(), 0);
if (bytes_received < 0) {
std::cerr << "Error receiving data" << std::endl;
} else if (bytes_received == 0) {
std::cout << "Server disconnected" << std::endl;
} else {
buffer.resize(bytes_received);
std::cout << "Received from server: " << buffer << std::endl;
}
// 关闭连接
close(sockfd);
return 0;
}
总结:
recv
函数在C++ Linux环境中用于接收socket连接中的数据,是实现客户端-服务器通信的关键函数之一。通过结合socket
、bind
、listen
、accept
、send
和recv
等函数,可以构建功能完善的网络应用程序。在实际应用中,需要注意错误处理、线程安全以及资源释放等问题,以确保程序的 robustness 和可靠性。
[
\boxed{recv函数是用于接收数据的socket函数,原型为ssize_t recv(int sockfd, void *buf, size_t len, int flags);。它在服务端和客户端的通信中扮演着 crucial的角色,用于接收对方发送的数据。通过结合其他socket函数,可以实现完整的客户端-服务器通信。}
]