SEND - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
send,sendto,sendmsg-在套接字上发送消息
语法
#include <sys/types.h> #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);
说明
系统调用send(),sendto()和sendmsg()用于将消息传输到另一个套接字。
仅当套接字处于连接状态时才能使用send()调用(这样才能知道预期的接收者)。 send()和write(2)之间的唯一区别是标志的存在。使用零标志参数时,send()等效于write(2)。还有,下面的电话
发送(sockfd,buf,len,flags);
相当于
sendto(sockfd,buf,len,flags,NULL,0);
参数sockfd是发送套接字的文件描述符。
如果在连接模式(SOCK_STREAM,SOCK_SEQPACKET)套接字上使用sendto(),则忽略dest_addr和addrlen参数(当它们不是NULL和0时可能返回错误EISCONN),并且当套接字实际上没有连接。否则,目标地址由dest_addr给出,其中addrlen指定其大小。对于sendmsg(),目标的地址由msg.msg_name给出,其中msg.msg_namelen指定其大小。
对于send()和sendto(),该消息位于buf中,长度为len。对于sendmsg(),消息由msg.msg_iov数组的元素指向。 sendmsg()调用还允许发送辅助数据(也称为控制信息)。
如果消息太长而无法自动通过基础协议,则返回错误EMSGSIZE,并且不发送消息。
send()中没有隐式表示无法交付失败的指示。本地检测到的错误由返回值-1表示。
当消息不适合套接字的发送缓冲区时,除非套接字已置于非阻塞I / O模式,否则send()通常会阻塞。在非阻塞模式下,在这种情况下,它将失败并显示错误EAGAIN或EWOULDBLOCK。 select(2)调用可用于确定何时可以发送更多数据。
The flags argument
flags参数是零个或多个以下标志的按位或。
- MSG_CONFIRM(since Linux 2.3.15)
- 告诉链接层前进的进度发生了:您从另一侧获得了成功的答复。如果链路层没有收到此消息,它将定期重新探测邻居(例如,通过单播ARP)。仅在SOCK_DGRAM和SOCK_RAW套接字上有效,并且当前仅对IPv4和IPv6实现。有关详细信息,请参见arp(7)。
- MSG_DONTROUTE
- 不要使用网关发送数据包,而只发送到直接连接的网络上的主机。通常仅由诊断程序或路由程序使用。仅为路由的协议族定义此属性。数据包套接字没有。
- MSG_DONTWAIT(since Linux 2.2)
- 启用非阻塞操作;如果操作将阻塞,则返回EAGAIN或EWOULDBLOCK。这提供了与设置O_NONBLOCK标志类似的行为(通过fcntl(2)F_SETFL操作),但不同之处在于MSG_DONTWAIT是按调用的选项,而O_NONBLOCK是打开文件说明中的设置(请参见open(2)),这将影响调用进程中的所有线程以及保存引用同一打开文件描述的文件描述符的其他进程。
- MSG_EOR(since Linux 2.2)
- 终止记录(当支持此概念时,如SOCK_SEQPACKET类型的套接字)。
- MSG_MORE(since Linux 2.4.4)
- 呼叫者有更多数据要发送。此标志与TCP套接字一起使用,可获得与TCP_CORK套接字选项相同的效果(请参阅tcp(7)),不同之处在于可以根据每次调用设置此标志。
- 从Linux 2.6开始,UDP套接字也支持该标志,并通知内核将设置了该标志的调用中发送的所有数据打包到单个数据报中,该数据报仅在执行未指定此标志的调用时才发送。 (另请参见udp(7)中描述的UDP_CORK套接字选项。)
- MSG_NOSIGNAL(since Linux 2.2)
- 如果面向流的套接字上的对等方已关闭连接,请不要生成SIGPIPE信号。 EPIPE错误仍然返回。这提供了与使用sigaction(2)忽略SIGPIPE相似的行为,但是,尽管MSG_NOSIGNAL是按调用的功能,但是忽略SIGPIPE会设置一个影响进程中所有线程的进程属性。
- MSG_OOB
- 在支持此概念的套接字(例如SOCK_STREAM类型)上发送带外数据;基础协议还必须支持带外数据。
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。
与writev(2)一样,msg_iov和msg_iovlen字段指定分散收集位置。
您可以使用msg_control和msg_controllen成员发送控制信息。每个套接字,内核可以处理的最大控制缓冲区长度受/ proc / sys / net / core / optmem_max中的值限制;参见socket(7)。
msg_flags字段将被忽略。
返回值
成功后,这些调用将返回发送的字节数。如果出错,则返回-1,并正确设置errno。
错误说明
这些是套接字层生成的一些标准错误。可能会产生其他错误并从底层协议模块中返回这些错误;请参阅各自的手册页。
- EACCES
- (对于UNIX域套接字,由路径名标识)对目标套接字文件的写许可权被拒绝,或者对路径前缀目录之一的搜索许可权被拒绝。 (请参阅path_resolution(7)。)
- (对于UDP套接字)试图发送到网络/广播地址,就好像它是单播地址一样。
- EAGAINor EWOULDBLOCK
- 套接字被标记为非阻塞,并且请求的操作将阻塞。 POSIX.1-2001允许在这种情况下返回任何一个错误,并且不需要这些常量具有相同的值,因此可移植应用程序应检查这两种可能性。
- EAGAIN
- (Internet域数据报套接字)sockfd引用的套接字以前未绑定到地址,并且在尝试将其绑定到临时端口后,确定当前临时端口范围内的所有端口号都在使用中。请参阅ip(7)中对/ proc / sys / net / ipv4 / ip_local_port_range的讨论。
- EALREADY
- 另一个快速开放正在进行中。
- EBADF
- sockfd不是有效的打开文件描述符。
- ECONNRESET
- 对等方重置连接。
- EDESTADDRREQ
- 套接字不是连接模式,并且未设置对等地址。
- EFAULT
- 为参数指定了无效的用户空间地址。
- EINTR
- 在传输任何数据之前发生信号;参见signal(7)。
- EINVAL
- 传递了无效的参数。
- EISCONN
- 连接模式套接字已经连接,但是指定了收件人。 (现在,要么返回此错误,要么忽略收件人规范。)
- EMSGSIZE
- 套接字类型要求以原子方式发送消息,并且要发送的消息大小使此操作无法实现。
- ENOBUFS
- 网络接口的输出队列已满。通常,这表明接口已停止发送,但是可能是由于瞬时拥塞引起的。 (通常,这在Linux中不会发生。当设备队列溢出时,数据包只会被静默丢弃。)
- ENOMEM
- 没有可用的内存。
- ENOTCONN
- 套接字未连接,并且未指定目标。
- ENOTSOCK
- 文件描述符sockfd不引用套接字。
- EOPNOTSUPP
- flags参数中的某些内容不适用于套接字类型。
- EPIPE
- 本端已在面向连接的套接字上关闭。在这种情况下,除非设置了MSG_NOSIGNAL,否则该进程还将收到SIGPIPE。
遵循规范
4.4BSD,SVr4,POSIX.1-2001。这些接口最早出现在4.2BSD中。
POSIX.1-2001仅描述了MSG_OOB和MSG_EOR标志。 POSIX.1-2008添加了MSG_NOSIGNAL的规范。 MSG_CONFIRM标志是Linux扩展。
备注
根据POSIX.1-2001,msghdr结构的msg_controllen字段应键入socklen_t,msg_iovlen字段应键入int,但glibc当前都将其键入为size_t。
有关特定于Linux的系统调用的信息,请参见sendmmsg(2),该系统调用可用于在单个调用中传输多个数据报。
BUGS
Linux可能会返回EPIPE而不是ENOTCONN。
示例
getaddrinfo(3)中显示了使用sendto()的示例。
另外参见
fcntl(2),getsockopt(2),recv(2),select(2),sendfile(2),sendmmsg(2),shutdown(2),socket(2),write(2),cmsg(3), ip(7),ipv6(7),套接字(7),tcp(7),udp(7),unix(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。