linux C语言socket函数send

在Linux中,使用C语言进行网络编程时,send函数是用于发送数据到已连接的套接字的重要函数之一。它通常用于TCP连接,但也可以用于UDP(尽管对于UDP,通常更推荐使用sendto,因为它允许你指定目标地址和端口)。

下面是send函数的详细解释:

函数原型

recv 函数在 <sys/socket.h> 中定义,其函数原型如下:

#include <sys/types.h>
#include <sys/socket.h>

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

参数

  1. sockfd
    这是一个已打开的套接字描述符,它标识了要通过其发送数据的网络连接。对于TCP,这个套接字通常是通过socket函数创建的,并且已经通过connect函数与远程服务器建立了连接。

  2. buf
    这是一个指向要发送数据的缓冲区的指针。这个缓冲区包含了要通过网络发送的字节流。缓冲区中的数据在调用send函数时并不会被自动修改。

  3. len
    这是要发送数据的长度,以字节为单位。它指定了buf指针指向的缓冲区中有效数据的量。

  4. flags
    这是一个整数值,用于传递特殊的发送标志给底层协议。这些标志可以修改send函数的行为。通常,这个参数被设置为0,表示使用标准的发送行为。然而,一些可能的标志包括:

    • MSG_OOB:发送带外数据(out-of-band data),这是一种紧急数据,通常用于TCP连接。
    • MSG_DONTROUTE:绕过标准的路由表查找,通常用于本地通信。
    • MSG_NOSIGNAL:请求不发送SIGPIPE信号,如果接收端已经关闭了连接,则send函数将返回错误而不是终止进程。

返回值

  • 如果成功,send函数返回实际发送的字节数。这个数字可能小于len参数指定的长度,这取决于套接字的发送缓冲区可用空间和网络条件。
  • 如果出现错误,send函数返回-1,并设置全局变量errno以指示错误类型。

错误处理

send函数返回-1时,可以检查errno来确定错误的原因。一些常见的错误包括:

  • EWOULDBLOCKEAGAIN:套接字是非阻塞的,并且没有足够的缓冲区空间可供立即发送数据。
  • ECONNRESET:连接被对端重置。
  • EPIPE:对端关闭了连接,并且启用了SIGPIPE信号(除非设置了MSG_NOSIGNAL标志)。
  • EBADF:提供的套接字描述符不是有效的或不支持发送操作。
  • EINTR:发送操作被中断,通常是因为接收到了一个信号。

注意事项

  1. 阻塞与非阻塞:根据套接字的配置,send函数可以表现为阻塞或非阻塞。在阻塞模式下,send会等待直到有足够的缓冲区空间可以发送数据或发生错误。在非阻塞模式下,如果没有足够的缓冲区空间,send会立即返回EWOULDBLOCKEAGAIN错误。

  2. 多次发送:即使send的返回值小于请求的len,也不意味着发送失败。在TCP中,由于流量控制和窗口大小,可能需要多次调用send来发送所有数据。

  3. 数据完整性send函数不保证数据的原子性。如果需要在两个进程或两台机器之间原子性地发送数据,通常需要在应用层实现额外的协议。

  4. 关闭连接:当对端关闭连接时,继续向其发送数据可能会导致EPIPE错误(如果未设置MSG_NOSIGNAL标志)或SIGPIPE信号。

  5. 性能考虑:频繁地发送小块数据可能不如一次性发送大块数据高效,因为网络传输和操作系统调用都有一定的开销。

在使用send函数时,务必考虑上述因素,并适当地处理可能的错误和异常情况。

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main() {
    // 假定 sockfd 是已经连接好的套接字
    int sockfd = /* socket(...) */;
    
    // 用于存储接收数据的缓冲区
    char buffer[1024];
    
    // 清空缓冲区
    memset(buffer, 0, sizeof(buffer));
    
    // 接收数据
    int bytes_received = recv(sockfd, buffer, sizeof(buffer), 0);
    if (bytes_received < 0) {
        // 处理错误
        perror("recv failed");
    } else if (bytes_received == 0) {
        // 对方已经关闭了连接
        printf("Peer has performed an orderly shutdown\n");
    } else {
        // 打印接收到的数据
        printf("Received (%d bytes): %.*s\n", bytes_received, bytes_received, buffer);
    }
    
    // 关闭套接字
    close(sockfd);
    
    return 0;
}

在上面的代码示例中,`sockfd` 应已经是一个成功连接的 socket—这意味着在 TCP 的情况下,应该在客户端使用 connect 或在服务器端使用 accept 来获得 sockfd

在实际应用程序中,通常会将 recv 放在某个循环中以持续接收数据。当 recv 返回 0 表示对方已经关闭了连接,接收循环就应该结束。还需要处理各种可能出现的错误。

perror 函数是一个标准的C库函数,用于打印一个描述性的错误消息到标准错误输出 stderr。它会根据全局变量 errno 的当前值来显示当前错误的文本描述。
errno 是在发生系统调用或库函数调用出错时设置的全局变量,它的值表示错误的类型。<errno.h> 头文件定义了errno 可能的错误代码(例如 EACCES、ECONNRESET 等)和对应的错误信息。
perror 的原型定义如下:

#include <stdio.h>
void perror(const char *s);

当你调用 perror 时,你可以提供一个字符串作为参数,perror会先打印这个字符串,后接一个冒号和一个空格,然后是对应 errno 值的字符串描述。最后,它会添加一个换行符。
例如:

if (write(fd, buf, count) == -1) {
    perror("write failed");
    // 这里还可以包含额外的错误处理代码
}

如果 write 调用失败,你将看到像 "write failed: Permission denied" 这样的错误消息被打印到标准错误输出。
如果 errno 值是0,表示没有发生错误,perror函数通常不会打印有关错误的信息。
为了确保 perror显示的是你关心的错误信息,最好在调用可能设置errno的函数之后立即使用perror— 在任何其他可能再次设置 errno 的操作之前。这是因为许多函数都可能更改 errno 值,包括成功的函数调用。通常,在检查函数调用返回值时,如果发现它出错(通常返回值是 -1 或者 NULL),马上用 perror 来查看错误原因。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/335015.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

插入排序(一)——直接插入排序与希尔排序

目录 一.前言 二.排序的概念及其运用 1.1排序的概念 1.2 常用排序算法 三.常用排序算法的实现 3.1 插入排序 3.1.1 基本思想 3.1.2 直接插入排序 3.1.3 希尔排序&#xff08;缩小增量排序&#xff09; 四.全部代码 sort.c sort.h test.c 五.结语 一.前言 本文我们…

SpringBoot 3.1.7 集成Mybatis

一、介绍 Mybatis的中文官网并没找到与SpringBoot最新的集成的教程&#xff0c;有的都是老式的配置方法&#xff0c;所以记录一下怎么我是怎么集成SpringBoot 3.1.7 集成Mybatis 的方法 有条件的可以打开源网站 https://github.com/mybatis/spring-boot-starter 没有条件的我…

虚拟机下载docker

一&#xff0c;Docker简介 百科说&#xff1a;Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化&#xff0c;容器是完全使用沙箱机制&#xff…

GetShell的姿势

0x00 什么是WebShell 渗透测试工作的一个阶段性目标就是获取目标服务器的操作控制权限&#xff0c;于是WebShell便应运而生。Webshell中的WEB就是web服务&#xff0c;shell就是管理攻击者与操作系统之间的交互。Webshell被称为攻击者通过Web服务器端口对Web服务器有一定的操作权…

nodejs前端项目的CI/CD实现(二)jenkins的容器化部署

一、背景 docker安装jenkins&#xff0c;可能你会反问&#xff0c;这太简单了&#xff0c;有什么好讲的。 我最近就接手了一个打包项目&#xff0c;它是一个nodejs的前端项目&#xff0c;jenkins已在容器里部署且运行OK。 但是&#xff0c;前端组很追求新技术&#xff0c;不…

【STM32】STM32学习笔记-I2C通信外设(34)

00. 目录 文章目录 00. 目录01. I2C简介02. I2C外设简介03. I2C框图04. I2C基本结构05. 主机发送06. 主机接收07. 软件/硬件波形对比08. 预留09. 附录 01. I2C简介 I2C(Inter&#xff0d;Integrated Circuit)总线是一种由NXP&#xff08;原PHILIPS&#xff09;公司开发的两线式…

Web3艺术市场:NFT与数字创作的结合

在数字时代&#xff0c;随着区块链技术的崛起&#xff0c;一种新型数字资产&#xff0c;非同质化代币&#xff08;NFT&#xff09;&#xff0c;正逐渐改变传统艺术市场的格局。这种数字化的艺术品售卖方式成为了Web3艺术市场的代表&#xff0c;推动着数字创作与艺术市场的结合。…

深度学习—常见的卷积操作和卷积神经网络

各种常见的卷积操作 0、三种模式及输出矩阵尺寸计算 W输入矩阵宽&#xff0c;w是卷积核的大小&#xff0c;p是padding的数值&#xff0c;stride是滑动步幅 Full 补k-1圈 &#xff1a;w0 &#xff08; | W | - w 2p &#xff09;/ stride 1 Same 补若干圈&#xff1a;w0 …

UI组件在线预览,程序员直呼“不要太方便~”

一、介绍 以往大家如果想查看组件的使用效果&#xff0c;需要打开DevEco Studio构建工程。现在为了便于大家高效开发&#xff0c;文档上线了JS UI组件在线预览功能&#xff0c;无需本地构建工程&#xff0c;在线即可修改组件样式等参数、一键预览编译效果。程序员直呼&#xff…

使用 ClassFinal 对SpringBoot jar加密加固并进行机器绑定

写在前面&#xff1a;各位看到此博客的小伙伴&#xff0c;如有不对的地方请及时通过私信我或者评论此博客的方式指出&#xff0c;以免误人子弟。多谢&#xff01;如果我的博客对你有帮助&#xff0c;欢迎进行评论✏️✏️、点赞&#x1f44d;&#x1f44d;、收藏⭐️⭐️&#…

回溯算法篇-02:括号生成

力扣22、括号生成 题目分析 对于括号类问题&#xff0c;有以下两个性质&#xff1a; 一个“合法”的括号组合中&#xff0c;左括号数量一定等于右括号数量对于一个 “合法” 的括号字符串组合 p &#xff0c;必然对于任何 0 < i < len(p) 都有&#xff1a;子串 p[0...i…

商铺工厂119消防火灾SOS声光一键报警器平台联网

商铺工厂119消防火灾SOS声光一键报警器平台联网 1.设有火灾自动报警系统的建筑&#xff0c;宜选择符合相关现行国家技术标准的消防应急广播、火灾声光警报类产品&#xff0c;由火灾报警或消防联动控制器进行控制&#xff0c;在消防控制室应能一键启动全楼火灾声光警报或向全楼进…

phpStorm 设置终端为git bash

环境&#xff1a; windows , PhpStorm 2022 为自己的终端配置git样式的使用&#xff0c; 默认终端样式 一、打开设置&#xff0c;选择git bin 二、重新打开终端 不加--login -i 的终端 加了--login -i 的终端 最重要的一点是什么&#xff0c;他可以像mac一样支持 ctrlv 复…

【Qt5】QString的成员函数chop

2024年1月19日&#xff0c;周五下午 QString 的 chop 方法用于从字符串的末尾移除指定数量的字符。这个方法会修改原始字符串&#xff0c;并返回 void。 下面是一个简单的示例&#xff1a; #include <QString> #include <QDebug>int main() {QString originalStr…

PE解释器之PE文件结构(二)

接下来的内容是对IMAGE_OPTIONAL_HEADER32中的最后一个成员DataDirectory&#xff0c;虽然他只是一个结构体数组&#xff0c;每个结构体的大小也不过是个字节&#xff0c;但是它却是PE文件中最重要的成员。PE装载器通过查看它才能准确的找到某个函数或某个资源。 一&#xff1…

安捷伦AgilentE8363B网络分析仪

安捷伦AgilentE8363B网络分析仪 E8363B 是 Agilent 的 40 GHz 网络分析仪。网络分析仪是一种功能强大的仪器&#xff0c;可以以无与伦比的精度测量射频设备的线性特性。许多行业使用网络分析仪来测试设备、测量材料和监控信号的完整性 附加功能&#xff1a; 104 dB 的动态范围…

Redis--HyperLogLog的指令语法与使用场景举例(UV统计)

文章目录 前言HyperLogLog介绍HyperLogLog指令使用使用场景&#xff1a;UV统计 前言 Redis除了常见的五种数据类型之外&#xff0c;其实还有一些少见的数据结构&#xff0c;如Geo&#xff0c;HyperLogLog等。虽然它们少见&#xff0c;但是作用却不容小觑。本文将介绍HyperLogL…

使用KTO进行更好、更便宜、更快速的LLM对齐

KTO全称为Kahneman-Tversky Optimisation&#xff0c;这种对齐方法使在我们的数据上对大型语言模型&#xff08;LLM&#xff09;进行对齐变得前所未有地容易和便宜&#xff0c;而且不会损害性能。大型语言模型的成功在很大程度上得益于与人类反馈的对齐。如果ChatGPT曾经拒绝回…

三星刚刚将Google Gemini集成到Galaxy S24中

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 AI手机的新时代即将到来。 三星刚刚将 Google Gemini 集成到 Galaxy S24 中&#xff01; 准备好迎接智能手机吧&#xff0c;它不仅智能&#xff0c;而且具有灵性。…

Jvm相关知识(面试高级必备)

类的实例化顺序 先静态、先父后子 先静态&#xff1a;父静态>子静态 优先级&#xff1a;父类>子类 静态代码块>非静态代码块>构造函数 一个类的实例化过程&#xff1a; ①&#xff0e;父类的static代码块&#xff0c;当前类的static; ②&#xff0e;顺序执行…