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

Linux下send函数和recv函数

1. 基本介绍

send 函数

send 函数用于向一个已连接的套接字发送数据。它的典型使用场景是在TCP通信中,客户端和服务器之间交换数据。

函数声明:

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

参数解释:

  • sockfd:套接字描述符,表示已连接的套接字。
  • buf:指向要发送的数据缓冲区。
  • len:要发送的数据字节数。
  • flags:控制数据发送行为的标志,可以为 0 或者使用一些选项(例如 MSG_DONTWAIT,非阻塞发送)。

返回值:

  • 成功时,返回发送的字节数。
  • 失败时,返回 -1,并设置相应的 errno 错误码。
recv 函数

recv 函数用于从已连接的套接字接收数据。通常和send函数配合使用。

函数声明:

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

参数解释:

  • sockfd:套接字描述符,表示已连接的套接字。
  • buf:指向接收数据的缓冲区。
  • len:缓冲区的大小,最大接收字节数。
  • flags:控制接收行为的标志,如 MSG_WAITALL(等待接收完整数据),MSG_PEEK(查看缓冲区中的数据,但不将其从缓冲区移除)。

返回值:

  • 成功时,返回接收到的字节数。
  • 如果对端正常关闭连接,返回 0。
  • 失败时,返回 -1,并设置 errno

2. 发送和接收的典型使用场景

TCP 通信中的 sendrecv
  • 在客户端-服务器模型中,通常会先由客户端发起连接,然后通过send函数发送请求数据,服务器通过recv接收请求并处理。
  • 服务器响应数据后,再使用send函数将结果返回给客户端,客户端通过recv获取返回结果。
UDP 通信中的 sendrecv

UDP是无连接的,因此可以使用sendtorecvfrom来指定目标地址和端口,进行数据的发送和接收。

3. flags 参数的常见选项

sendrecvflags 参数可以控制不同的发送和接收行为,常用的选项包括:

  • MSG_DONTWAIT:非阻塞模式,若无法立即发送或接收数据,sendrecv 会立刻返回而不是阻塞。
  • MSG_PEEK:查看缓冲区数据但不移除数据,常用于探测网络数据的到来。
  • MSG_OOB:发送或接收带外数据(TCP紧急数据)。
  • MSG_WAITALL:等待接收到指定大小的数据后才返回。

4. 常见错误及处理

  • EAGAINEWOULDBLOCK:在非阻塞模式下,数据无法立即发送或接收,需要等待套接字可用。
  • EINTR:操作被信号中断,通常可以重试。
  • ECONNRESET:连接被对端重置,通常意味着对端异常关闭了连接。

5. 示例代码

客户端使用示例
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    int sockfd;
    struct sockaddr_in server;
    char message[1000], server_reply[2000];

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("创建套接字失败\n");
    }

    server.sin_addr.s_addr = inet_addr("192.168.1.1");
    server.sin_family = AF_INET;
    server.sin_port = htons(8888);

    // 连接到远程服务器
    if (connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
        perror("连接失败");
        return 1;
    }

    // 发送数据
    strcpy(message, "Hello Server");
    if (send(sockfd, message, strlen(message), 0) < 0) {
        printf("发送失败\n");
        return 1;
    }

    // 接收服务器响应
    if (recv(sockfd, server_reply, 2000, 0) < 0) {
        printf("接收失败\n");
    }

    printf("服务器响应:%s\n", server_reply);

    close(sockfd);
    return 0;
}

服务器使用示例

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    int socket_desc, client_sock, c;
    struct sockaddr_in server, client;
    char client_message[2000];

    // 创建套接字
    socket_desc = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_desc == -1) {
        printf("无法创建套接字\n");
    }

    // 配置服务器地址结构
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(8888);

    // 绑定
    if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
        perror("绑定失败");
        return 1;
    }

    // 监听
    listen(socket_desc, 3);

    // 接受客户端连接
    c = sizeof(struct sockaddr_in);
    client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c);
    if (client_sock < 0) {
        perror("接受连接失败");
        return 1;
    }

    // 接收客户端消息
    if (recv(client_sock, client_message, 2000, 0) > 0) {
        printf("客户端消息:%s\n", client_message);
        
        // 发送响应
        send(client_sock, "Hello Client", strlen("Hello Client"), 0);
    }

    close(client_sock);
    close(socket_desc);
    return 0;
}

6. 总结

sendrecv 是套接字通信中的基础操作,理解它们的使用方式和参数对于编写可靠的网络程序至关重要。


http://www.kler.cn/news/328520.html

相关文章:

  • AWS Redshift把老用户权限赋予新用户
  • 201 Created
  • 如何在Windows、Mac和Linux系统上安装和更新Stable Diffusion WebUI
  • Spark SQL分析层优化
  • 中国电信解锁万亿参数大模型:TeleAI的创新与突破
  • Docker镜像命令和容器命令
  • 《征服数据结构》哈夫曼树(Huffman Tree)
  • Python 封装 socket 为 [TCP/UDP/MULTICAST] 服务端
  • 计算机毕业设计 服装生产信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
  • Datawhale Leecode基础算法篇 task04:贪心算法
  • SpringBoot 使用自定义注解和枚举类对接口入参校验
  • 2024年寒假开学赛题解
  • Python空间地表联动贝叶斯地震风险计算模型
  • 【SpringCloud】优雅实现远程调⽤-OpenFeign
  • python 实现rayleigh quotient瑞利商算法
  • 数据结构-4.3.串的存储结构
  • 深入理解网络通信: 长连接、短连接与WebSocket
  • Spring系列 AOP实现过程
  • 【PostgreSQL】入门篇——PostgreSQL 的历史、特点和优势
  • 开卷可扩展自动驾驶(OpenDriveLab)
  • express,MySQL 实现登录接口,如果用户未注册直接注册
  • 【Python】Uvicorn:Python 异步 ASGI 服务器详解
  • vue3 环境配置vue-i8n国际化
  • Linux高级IO之poll与epoll
  • 基于Springboot+微信小程序 的高校社团管理小程序(含源码+数据库+lw)
  • TypeScript 算法手册【插入排序】
  • 搜维尔科技:SenseGlove DK1触觉反馈手套,远程操作机器人任务,保证你工作时的安全
  • js无法获取执行的线程号(Thread ID)
  • 【Golang】关于Go语言中的包
  • 超分服务的分量保存