当前位置: 首页 > article >正文

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连接中的数据,是实现客户端-服务器通信的关键函数之一。通过结合socketbindlistenacceptsendrecv等函数,可以构建功能完善的网络应用程序。在实际应用中,需要注意错误处理、线程安全以及资源释放等问题,以确保程序的 robustness 和可靠性。
[
\boxed{recv函数是用于接收数据的socket函数,原型为ssize_t recv(int sockfd, void *buf, size_t len, int flags);。它在服务端和客户端的通信中扮演着 crucial的角色,用于接收对方发送的数据。通过结合其他socket函数,可以实现完整的客户端-服务器通信。}
]


http://www.kler.cn/a/528757.html

相关文章:

  • 论文阅读(十六):利用线性链条件随机场模型检测阵列比较基因组杂交数据的拷贝数变异
  • BW AO/工作簿权限配置
  • 如何使用 ChatBox AI 简化本地模型对话操作
  • 网站快速收录:如何设置robots.txt文件?
  • Python练习(3)
  • 玩转大语言模型——使用langchain和Ollama本地部署大语言模型
  • 【数据结构篇】时间复杂度
  • 读书笔记-《你的灯亮着吗?》
  • 嵌入式硬件篇---CPUGPUTPU
  • taskset -c 1-60
  • 5. 【Vue实战--孢子记账--Web 版开发】-- 主页UI
  • Python字典详解:从入门到实践
  • P3199 【[HNOI2009]最小圈】
  • 【自学笔记】Web前端的重点知识点-持续更新
  • 【llm对话系统】大模型 Llama 源码分析之 LoRA 微调
  • 【Vaadin flow 实战】第5讲-使用常用UI组件绘制页面元素
  • TOF技术原理和静噪对策
  • std::call_once的原理及使用
  • fpga系列 HDL:XILINX Vivado ILA FPGA 在线逻辑分析
  • CF 581A.Vasya the Hipster(Java实现)
  • XML DOM - 访问节点
  • Java线程认识和Object的一些方法ObjectMonitor
  • 基于 STM32 的智能电梯控制系统
  • SZU大学物理2实验报告|超声探伤实验
  • GPG格式介绍:什么是GPG?如何加密和解密?
  • C++哈希(链地址法)(二)详解