好好活就是有意义的事,有意义的事就是好好活
linux手册翻译  send(2)
linux手册翻译 send(2)

linux手册翻译 send(2)

send(2) – Linux manual page (man7.org)

\color{#A00000}{NAME}

send, sendto, sendmsg – send a message on a socket

\color{#A00000}{SYNOPSIS}
#include <sys/socket.h>

ssize_t send(int sockfd, const void* buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void* buf, size_t len, int flags,
               const struct sockaddr* dest_addr, socklen_t addrlen);
ssize_t sendmsg(int sockfd, const struct msghdr* msg, int flags);
\color{#A00000}{DESCRIPTION}

系统调用 send()、sendto() 和 sendmsg() 用于将消息传输到另一个套接字。

仅当套接字处于连接状态时才可以使用 send() 调用(以便知道预期的接收者,也就是说send()仅仅用于数据流类型的数据发送,对于TCP,服务端和客户端都可以使用send/recv;但是对于UDP,只能是客户端使用send/recv,服务端只能使用sendto/recvfrom,因为客户端是进行了connect操作知道要发送和接受的地址)。send() 和 write(2) 之间的唯一区别是存在flags参数。此外,
send(sockfd, buf, len, flags);
等价于
sendto(sockfd, buf, len, flags, NULL, 0);

参数 sockfd 是发送者套接字的文件描述符。

如果在连接模式的套接字(即套接字类型为SOCK_STREAM、SOCK_SEQPACKET)上使用 sendto(),则参数 dest_addr 和 addrlen 将被忽略(当它们不是NULL和0时可能返回错误EISCONN),若套接字没有实际连接(还没有三次握手建立连接)将返回错误ENOTCONN。 否则,目标地址由 dest_addr 给出,addrlen指定其大小。 对于 sendmsg(),目标地址由 msg.msg_name 给出,msg.msg_namelen 指定其大小。

对于 send() 和 sendto(),消息位于 buf 中,长度为 len。 对于sendmsg(),消息存放于msg.msg_iov 元素指向数组数据区(见下)中。 sendmsg() 调用还允许发送辅助数据(也称为控制信息)

如果消息太长而无法通过底层协议原子传递(too long to pass atomically through the underlying protocol),则返回错误 EMSGSIZE,并且不会传输消息。

No indication of failure to deliver is implicit in a send(). Locally detected errors are indicated by a return value of -1.

当消息不适合套接字的发送缓冲区时,send() 通常会阻塞,除非套接字已置于非阻塞 I/O 模式。 在这种情况下,在非阻塞模式下它会失败并显示错误 EAGAIN 或 EWOULDBLOCK。 select(2) 调用可用于确定何时可以发送更多数据

上面的的描述还是很笼统的,以TCP为例,按我的理解,我认为只要发送缓冲区有空闲位置,且此时协议栈没有向网络发送数据,那么就可以写入,对于阻塞模式,直到所有数据写入到缓冲区,就会返回,否则一直阻塞,对于非阻塞模式,是有一个超时时间的,这个由 SO_SNDTIMEO 选项控制,详细见socket(7),如果当前有空闲位置可以发即当前可写入,那么就写入到缓冲区,知道超时之前写入多少算多少,然后返回成功写入的字节数,如果超时时任何数据都没写出去,或者当前就是不可写入,那么返回-1 ,并设置errno为 EAGAIN 或 EWOULDBLOCK。

The flags argument

The flags argument is the bitwise OR of zero or more of the following flags.

  • MSG_CONFIRM
    Tell the link layer that forward progress happened: you got a successful reply from the other side. If the link layer doesn’t get this it will regularly reprobe the neighbor (e.g., via a unicast ARP). Valid only on SOCK_DGRAM and SOCK_RAW sockets and currently implemented only for IPv4 and IPv6. See arp(7) for details.
  • MSG_DONTROUTE
    Don’t use a gateway to send out the packet, send to hosts only on directly connected networks. This is usually used only by diagnostic or routing programs. This is defined only for protocol families that route; packet sockets don’t.
  • MSG_DONTWAIT
    启用非阻塞操作;如果操作阻塞,将返回EAGAIN 或 EWOULDBLOCK。这提供了与设置 O_NONBLOCK 标志类似的行为(通过 fcntl(2) F_SETFL 操作),但不同之处在于 MSG_DONTWAIT 是每次调用的选项,而 O_NONBLOCK 是打开文件描述上的设置(请参阅 open(2)), 后者将影响调用进程中的所有线程以及保存引用相同打开文件描述的文件描述符的其他进程。
  • MSG_EOR
    Terminates a record (when this notion is supported, as for sockets of type SOCK_SEQPACKET).
  • MSG_MORE
    调用者有更多的数据要发送。此标志用于TCP套接字以获得与TCP_CORK套接字选项相同的效果(参见TCP(7)),不同之处在于此标志可以在每次调用时设置。
    如果要使用 sendfile() 将文件发送到 TCP 套接字,但需要在文件内容之前发送一些标头数据,比如说HTTP请求中发送一个静态文件
    从Linux 2.6开始,UDP套接字也支持这个标志,并通知内核将所有在调用中发送的数据打包到一个单独的数据报中,该数据报只有在执行没有指定这个标志的调用时才会发送。(参见udp(7)中描述的UDP_CORK套接字选项。)
    根据TCP(7),TCP_CORK的作用是:如果设置,则不发送部分帧。 当再次清除该选项时,将发送所有排队的部分帧。
    sendfile(2)的NOTES部分也有相关讨论。
  • MSG_NOSIGNAL
    如果面向流的套接字上的对等方已关闭连接,则不要生成 SIGPIPE 信号。 仍然返回 EPIPE 错误。 这提供了与使用 sigaction(2) 忽略 SIGPIPE 类似的行为,但是,虽然 MSG_NOSIGNAL 是每次调用的功能,但忽略 SIGPIPE 会设置影响进程中所有线程的进程属性。
  • MSG_OOB
    Sends out-of-band data on sockets that support this notion (e.g., of type SOCK_STREAM); the underlying protocol must also support out-of-band data.

sendmsg()

sendmsg() 使用的 msghdr 结构的定义如下:

struct msghdr {
    void         *msg_name;       /* Optional address */
    socklen_t     msg_namelen;    /* Size of address */

    struct iovec *msg_iov;        /* Scatter/gather array */
    size_t        msg_iovlen;     /* # elements in msg_iov */

    void         *msg_control;    /* Ancillary data, see below */
    size_t        msg_controllen; /* Ancillary data buffer len */
    int           msg_flags;      /* Flags (unused) */
};

对于未连接的套接字msg_name指定数据报的目标地址,它指向一个包含地址的缓冲区; msg_namelen字段应设置为地址的大小。 对于连接的套接字,这些字段应分别指定为 NULL 和 0。这里的未连接指的是数据报协议,连接指的是数据流协议

The msg_iov and msg_iovlen fields specify scatter-gather locations, as for writev(2).
msg_iov是一个buffer数组:

struct iovec {
    void  *iov_base;    /* Starting address */
    size_t iov_len;     /* Number of bytes to transfer */
};

使用 msg_control 和 msg_controllen 成员发送控制信息(辅助数据)。 内核可以处理的每个套接字最大控制缓冲区长度由 /proc/sys/net/core/optmem_max 中的值限制; 见socket(7)。 有关在各种套接字域中使用辅助数据的更多信息,请参阅 unix(7) 和 ip(7)。

msg_flags 字段被忽略。

\color{#A00000}{RETURN VALUE}

成功时,返回成功发送的字节数,这个字节数并不一定和我们的缓冲区大小相同。 出错时,返回 -1,并设置 errno 以指示错误。

\color{#A00000}{ERRORS}

这些是套接字层生成的一些标准错误。 底层协议模块可能会产生和返回额外的错误; 请参阅它们各自的手册页。

  • EACCES
    (对于 UNIX 域套接字,由路径名标识)对目标套接字文件的写入权限被拒绝,或者路径前缀的目录之一的搜索权限被拒绝。 (请参阅 path_resolution(7)。)
    (对于 UDP 套接字)尝试发送到网络/广播地址,就好像它是单播地址一样。
  • EAGAIN or EWOULDBLOCK
    在套接字被标记为非阻塞的情况下发生阻塞。 POSIX.1-2001 允许在这种情况下返回任一错误,并且不要求这些常量具有相同的值,因此可移植应用程序应检查这两种可能性。
  • EAGAIN
    (Internet 域数据报套接字) sockfd 引用的套接字先前未绑定到地址,并且在尝试将其绑定到临时端口时,确定临时端口范围内的所有端口号当前都在使用中。 请参阅 ip(7) 中对 /proc/sys/net/ipv4/ip_local_port_range 的讨论。
  • EALREADY
    Another Fast Open is in progress.
  • EBADF
    sockfd is not a valid open file descriptor.
  • ECONNRESET
    Connection reset by peer.
  • EDESTADDRREQ
    The socket is not connection-mode, and no peer address is set.
  • EFAULT
    An invalid user space address was specified for an argument.
  • EINTR
    A signal occurred before any data was transmitted; see signal(7).
  • EINVAL
    Invalid argument passed.
  • EISCONN
    连接模式套接字已连接,但指定了接收者。 这是对于sendto()和sendmsg()而言的。
  • EMSGSIZE
    The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible.
    UDP中,要发送的数据大小超过了发送缓冲区的限制。
  • ENOBUFS
    The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion. (Normally, this does not occur in Linux. Packets are just silently dropped when a device queue overflows.)
  • ENOMEM
    No memory available.
  • ENOTCONN
    The socket is not connected, and no target has been given.这是对于TCP下的send而言的,即没有connect
  • ENOTSOCK
    The file descriptor sockfd does not refer to a socket.
  • EOPNOTSUPP
    flags 参数中的某些位不适用于套接字类型。
  • EPIPE
    本地端已在面向连接的套接字上关闭。 在这种情况下,除非设置了 MSG_NOSIGNAL,否则进程也会收到一个 SIGPIPE
\color{#A00000}{CONFORMING TO}

4.4BSD, SVr4, POSIX.1-2001. These interfaces first appeared in 4.2BSD.

POSIX.1-2001 describes only the MSG_OOB and MSG_EOR flags. POSIX.1-2008 adds a specification of MSG_NOSIGNAL. The MSG_CONFIRM flag is a Linux extension.

\color{#A00000}{NOTES}

根据 POSIX.1-2001,msghdr 结构的 msg_controllen 字段应该是 socklen_t 类型,而 msg_iovlen 字段应该是 int 类型,但是 glibc 目前将两者都视为 size_t。

有关可用于在单个调用中传输多个数据报的 Linux 特定系统调用的信息,请参阅 sendmmsg(2)。

\color{#A00000}{BUGS}

Linux may return EPIPE instead of ENOTCONN.

\color{#A00000}{EXAMPLES}

getaddrinfo(3) 中显示了使用 send() 的示例。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注