linux C语言socket函数send

这篇具有很好参考价值的文章主要介绍了linux C语言socket函数send。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在Linux中,使用C语言进行网络编程时,send函数是用于发送数据到已连接的套接字的重要函数linux send函数,编程,# C语言,网络,linux,c语言之一。它通常用于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 来查看错误原因。文章来源地址https://www.toymoban.com/news/detail-828019.html

到了这里,关于linux C语言socket函数send的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Go语言网络编程(socket编程)http编程

    Web服务器的工作原理可以简单地归纳为 客户机通过TCP/IP协议建立到服务器的TCP连接 客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档 服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“

    2024年02月09日
    浏览(70)
  • Go语言网络编程(socket编程)WebSocket编程

    WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据 在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输 需要安装第

    2024年02月09日
    浏览(77)
  • Go语言网络编程(socket编程)TCP

    TCP协议 TCP/IP(Transmission Control Protocol/Internet Protocol) 即传输控制协议/网间协议,是一种面向连接(连接导向)的、可靠的、基于字节流的传输层(Transport layer)通信协议,因为是面向连接的协议,数据像水流一样传输,会存在黏包问题。 TCP服务端 一个TCP服务端可以同时连接很

    2024年02月09日
    浏览(58)
  • Go语言网络编程(socket编程)TCP粘包

    服务端代码如下: 客户端代码如下: 将上面的代码保存后,分别编译。先启动服务端再启动客户端,可以看到服务端输出结果如下: 收到client发来的数据: Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you?Hello, Hello. How are you? 收到client发来的数

    2024年02月09日
    浏览(66)
  • 【Linux】socket 编程(socket套接字介绍、字节序、socket地址、IP地址转换函数、套接字函数、TCP通信实现)

    橙色 所谓套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。 一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进程通

    2024年02月09日
    浏览(56)
  • Linux socket网络编程实战(tcp)实现双方聊天

    在上节已经系统介绍了大致的流程和相关的API,这节就开始写代码! 回顾上节的流程: 创建一个NET文件夹 来存放网络编程相关的代码: 这部分先实现服务器的连接部分的代码并进行验证 server1.c: 代码验证: 先编译并运行这部分代码: 可见,此时没有客户端进行连接,程

    2024年02月03日
    浏览(51)
  • Linux网络编程- 原始套接字(Raw Socket)

    原始套接字(Raw Socket)提供了一种机制,允许应用程序直接访问底层传输协议,绕过操作系统提供的传输层接口。这种套接字通常用于实现新的协议或对现有协议进行低级别的操作。 以下是对原始套接字的详细介绍: 定义与用途 : 原始套接字是直接基于网络层(如IP)的。

    2024年02月07日
    浏览(56)
  • Linux网络编程:socket实现client/server通信

    阅读 UNIX网络编程 卷1:套接字联网API 第3版 的前4个章节,觉得有必要对书籍上的源码案例进行复现,并推敲TCP的C/S通信过程。 📌 测试环境:CentOS7.6 x64 编译server.c 和 client.c gcc server.c -g -std=gnu99 -o server 和 gcc client.c -g -std=gnu99 -o client 运行测试: 📌 server.c仅仅实现对单个客户

    2024年02月03日
    浏览(41)
  • Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

    socket(套接字),用于网络中不同主机间进程的通信。 socket是一个伪文件,包含读缓冲区、写缓冲区。 socket必须成对出现。 socket可以建立主机进程间的通信,但需要协议(IPV4、IPV6等)、port端口、IP地址。          (1)创建流式socket套接字。                 a)此s

    2024年02月11日
    浏览(65)
  • 【Linux网络】网络编程套接字 -- 基于socket实现一个简单UDP网络程序

    我们把数据从A主机发送到B主机,是目的吗?不是,真正通信的不是这两个机器!其实是这两台机器上面的软件(人) 数据有 IP(公网) 标识一台唯一的主机 ,用谁来标识各自主机上客户或者服务进程的唯一性呢? 为了更好的表示一台主机上服务进程的唯一性,我们采用 端口号

    2024年02月12日
    浏览(159)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包