linux手册翻译——send(2)

2021-07-02  本文已影响0人  蟹蟹宁

\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.

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

\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() 的示例。

上一篇 下一篇

猜你喜欢

热点阅读