send() - Unix 和 Linux 系统调用
Tutorials Point


  Unix 初学者指南
  Unix Shell 编程
  高级 Unix
  Unix 有用参考
  Unix 有用资源
  精选阅读

版权所有 © 2014 tutorialspoint



  首页     参考     讨论论坛     关于 TP  

send() - Unix 和 Linux 系统调用


previous next AddThis Social Bookmark Button

广告

名称

send、sendto、sendmsg - 在套接字上发送消息

语法

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

ssize_t send(int s, const void *buf, size_t len, int flags);
ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
ssize_t sendmsg(int s, const struct msghdr *msg, int flags);

描述

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

只有当套接字处于 已连接 状态(以便知道目标接收方)时,才能使用 send() 调用。send() 和 write() 之间的唯一区别是 flags 的存在。当 flags 参数为零时,send() 等效于 write()。此外,send(s,buf,len,flags) 等效于 sendto(s,buf,len,flags,NULL,0)。

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

如果在连接模式(SOCK_STREAM、SOCK_SEQPACKET)套接字上使用 sendto(),则参数 totolen 将被忽略(并且当它们不为 NULL 和 0 时可能会返回错误 EISCONN),并且当套接字实际上未连接时会返回错误 ENOTCONN。否则,目标的地址由 to 给出,tolen 指定其大小。对于 sendmsg(),目标的地址由 msg.msg_name 给出,msg.msg_namelen 指定其大小。

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

如果消息过长而无法通过底层协议原子地传递,则会返回错误 EMSGSIZE,并且不会传输消息。

send() 中没有关于传递失败的隐式指示。本地检测到的错误由返回值 -1 指示。

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

flags 参数是以下标志的按位或。

标签描述
MSG_CONFIRM(仅限 Linux 2.3+)
 告诉链路层发生了转发进度:您从另一端获得了成功的回复。如果链路层没有收到此信息,它将定期探测邻居(例如,通过单播 ARP)。仅在 SOCK_DGRAMSOCK_RAW 套接字上有效,并且目前仅在 IPv4 和 IPv6 上实现。有关详细信息,请参阅 arp(7)。
MSG_DONTROUTE
 不要使用网关发送数据包,只发送到直接连接网络上的主机。这通常仅由诊断或路由程序使用。这仅为路由协议族定义;数据包套接字没有。
MSG_DONTWAIT
 启用非阻塞操作;如果操作将阻塞,则返回 EAGAIN(这也可以使用 O_NONBLOCKF_SETFL fcntl(2) 一起启用)。
MSG_EOR
 终止记录(当支持此概念时,例如对于类型为 SOCK_SEQPACKET 的套接字)。
MSG_MORE(自 Linux 2.4.4 起)
 调用方有更多数据要发送。此标志与 TCP 套接字一起使用以获得与 TCP_CORK 套接字选项相同的效果(请参阅 tcp(7)),区别在于此标志可以在每次调用时设置。

自 Linux 2.6 起,此标志也受 UDP 套接字支持,并通知内核将使用此标志设置的所有发送数据打包到单个数据报中,该数据报仅在执行未指定此标志的调用时传输。(另请参阅 udp(7) 中描述的 UDP_CORK 套接字选项)。

MSG_NOSIGNAL
 请求在面向流的套接字上发生错误时,不要发送 SIGPIPE,当另一端断开连接时。仍然会返回 EPIPE 错误。
MSG_OOB
 在支持此概念的套接字(例如类型为 SOCK_STREAM 的套接字)上发送 带外 数据;底层协议也必须支持 带外 数据。
msghdr 结构的定义如下。有关其字段的确切描述,请参阅 recv(2) 和以下内容。

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 */ socklen_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ };

您可以使用 msg_controlmsg_controllen 成员发送控制信息。内核可以处理的最大控制缓冲区长度受 net.core.optmem_max sysctl 每个套接字限制;请参阅 socket(7)。

返回值

成功时,这些调用返回发送的字符数。发生错误时,返回 -1,并且 errno 被相应地设置。

错误

这些是套接字层生成的一些标准错误。其他错误可能会从底层协议模块生成并返回;请参阅其各自的手册页。
标签描述
EACCES (对于由路径名标识的 Unix 域套接字)目标套接字文件上拒绝写入权限,或者路径前缀之一的目录上拒绝搜索权限。(请参阅 path_resolution(2)。)
EAGAINEWOULDBLOCK
 套接字标记为非阻塞,并且请求的操作将阻塞。
EBADF 指定了无效的描述符。
ECONNRESET
 连接被对等方重置。
EDESTADDRREQ
 套接字不是连接模式,并且未设置对等地址。
EFAULT 为参数指定了无效的用户空间地址。
EINTR 在任何数据传输之前发生了信号。
EINVAL 传递了无效的参数。
EISCONN
 连接模式套接字已连接,但指定了接收方。(现在,要么返回此错误,要么忽略接收方规范。)
EMSGSIZE
 套接字类型要求消息被原子地发送,并且要发送的消息的大小使得这不可能。
ENOBUFS
 网络接口的输出队列已满。这通常表示接口已停止发送,但可能是由瞬态拥塞引起的。(通常,这不会在 Linux 中发生。当设备队列溢出时,数据包会被静默丢弃。)
ENOMEM 没有可用的内存。
ENOTCONN
 套接字未连接,并且未给出目标。
ENOTSOCK
 参数 s 不是套接字。
EOPNOTSUPP
 flags 参数中的某些位不适用于套接字类型。
EPIPE 本地端已在面向连接的套接字上关闭。在这种情况下,进程也将接收 SIGPIPE,除非设置了 MSG_NOSIGNAL

符合标准

4.4BSD、SVr4、POSIX.1-2001。这些函数调用出现在 4.2BSD 中。

POSIX.1-2001 仅描述 MSG_OOBMSG_EOR 标志。MSG_CONFIRM 标志是 Linux 扩展。

备注

上面给出的原型遵循 Single Unix Specification,就像 glibc2 一样;flags 参数在 4.x BSD 中是 ‘int’,但在 libc4 和 libc5 中是 ‘unsigned int’;len 参数在 4.x BSD 和 libc4 中是 ‘int’,但在 libc5 中是 ‘size_t’;tolen 参数在 4.x BSD 和 libc4 和 libc5 中是 ‘int’。另请参阅 accept(2)。

根据 POSIX.1-2001,msghdr 结构的 msg_controllen 字段应类型化为 socklen_t,但 glibc 当前(2.4)将其类型化为 size_t

错误

Linux 可能会返回 EPIPE 而不是 ENOTCONN。

参见



previous next Printer Friendly

广告


  

广告



广告