send, sendto, sendmsg - send a message on a socket
系统调用 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 is the bitwise OR of zero or more of the following flags.
sendmsg() 使用的 msghdr 结构的定义如下:
对于未连接的套接字 msg_name 指定数据报的目标地址,它指向一个包含地址的缓冲区; msg_namelen 字段应设置为地址的大小。 对于连接的套接字,这些字段应分别指定为 NULL 和 0。 这里的未连接指的是数据报协议,连接指的是数据流协议
The msg_iov and msg_iovlen fields specify scatter-gather locations, as for writev(2).
msg_iov是一个buffer数组:
使用 msg_control 和 msg_controllen 成员发送控制信息(辅助数据)。 内核可以处理的每个套接字最大控制缓冲区长度由 /proc/sys/net/core/optmem_max 中的值限制; 见 socket(7) 。 有关在各种套接字域中使用辅助数据的更多信息,请参阅 unix(7) 和 ip(7)。
msg_flags 字段被忽略。
成功时,返回成功发送的字节数,这个字节数并不一定和我们的缓冲区大小相同 。 出错时,返回 -1,并设置 errno 以指示错误。
这些是套接字层生成的一些标准错误。 底层协议模块可能会产生和返回额外的错误; 请参阅它们各自的手册页。
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.
根据 POSIX.1-2001,msghdr 结构的 msg_controllen 字段应该是 socklen_t 类型,而 msg_iovlen 字段应该是 int 类型,但是 glibc 目前将两者都视为 size_t。
有关可用于在单个调用中传输多个数据报的 Linux 特定系统调用的信息,请参阅 sendmmsg(2)。
Linux may return EPIPE instead of ENOTCONN.
getaddrinfo(3) 中显示了使用 send() 的示例。
iptables - 用于 IPv4 /IPv6数据包过滤和 NAT 的管理工具
iptables [-t table] {-A|-C|-D} chain rule-specification
iptables 和 ip6tables 用于在 Linux 内核中设置、维护和检查 IPv4 和 IPv6 包过滤规则的表。 可以定义几个不同的表。 每个表包含许多内置链,也可能包含用户定义的链。
每个链都包含了一个规则列表,可以匹配一组数据包。 每个规则都指定如何去处理匹配的数据包,即 Target ,如下图所示,表中有五个链:PREROUTING,INPUT,POSTROUTING,OUTPUT和DOCKER,其中链POSTROUTING拥有两个匹配规则,他们的Target分别是MASQUERADE和SNAT,即进行网络地址转换,链OUTPUT只有一条规则,其target是DOCKER,即数据包要交给链DOCKER进行进一步匹配处理。
数据包将在链上依次匹配规则,若不匹配,则检查下一条,若匹配,则根据target,执行下一步 *** 作。target的至可能是其他链的名字(如上面的DOCKER),则此时将数据包交给此链进行规则匹配;target还可能是其他特殊值:ACCEPT、DROP或 RETURN 之一。
如果到达内置链的末端或匹配带有目标 RETURN 的内置链中的规则,则链的策略将决定数据包的命运。链的策略在上图中,每个内置链名称后的括号中体现。
目前有五个独立的表(存在哪些表取决于内核配置选项和存在哪些模块)。
-t, --table table
此选项指定命令应 *** 作那个数据包匹配表。 如果内核配置了自动模块加载,则将尝试加载该表的适当模块(如果该模块尚不存在)。
三个表包括:
iptables 和 ip6tables 识别的Options可以分为几个不同的类别:
这些选项指定要执行的所需 *** 作。 除非下面另有说明,否则只能在命令行上指定其中之一。 对于长版本的命令和选项名称,您只需要使用足够多的字母以确保 iptables 可以将其与所有其他选项区分开来。
以下参数构成规则规范( rule-specification 在添加、删除、插入、替换和追加命令中使用)。
可以指定以下附加选项:
socket - 创建一个用于通信的端点
socket() 创建用于通信的端点并返回引用该端点的文件描述符。 成功调用时返回的文件描述符,将是当前没有被进程打开的所有文件描述符中编号最低的。
domain 参数指定一个通信域; 以决定用于通信的协议族。 这些系列在 <sys/socket.h>中定义。 目前 Linux 内核理解的格式包括:
当然最常用的当然是 AF_INET ,即IPV4。
上述地址族的更多详细信息以及其他几个地址族的信息可以在 address_families(7) 中找到。
套接字具有指定的 type ,它指定了通信语义。 当前定义的类型有:
某些套接字类型可能不会被所有协议族实现。
从 Linux 2.6.27 开始,type 参数有第二个用途:除了指定套接字类型之外,它还可以包含以下任何值的按位或,以修改 socket() 的行为:
老朋友了,上述两个,第一个是非阻塞,第二个是执行exec时自动关闭。
protocol 指定要与套接字一起使用的特定协议。 通常只存在一个协议来支持给定协议族中的特定套接字类型 ,在这种情况下,protocol 可以指定为 0。但是,可能存在许多协议,在这种情况下,必须在此指定特定协议方式。 特定协议对应的编号可以查看文件: /etc/protocols
SOCK_STREAM 类型的套接字是全双工字节流。 它们不保留记录边界。 流套接字必须处于连接状态,然后才能在其上发送或接收任何数据。 到另一个套接字的连接是通过 connect(2) 调用创建的。 连接后,可以使用 read(2) 和 write(2) 调用或 其变体send(2) 和 recv(2) 的来传输数据。 当会话完成时,可以执行 close(2)。 带外数据也可以按照 send(2) 中的描述进行传输,并按照 recv(2) 中的描述进行接收。
实现 SOCK_STREAM 的通信协议确保数据不会丢失或重复。 如果协议的缓冲空间中存在一条数据在合理的时间内不能成功传输,则认为该连接已失效。 当 SO_KEEPALIVE 在套接字上启用时,将会以特定于协议的方式检查另一端是否仍然存在。 如果进程在损坏的流上发送或接收,则会引发 SIGPIPE 信号; 这会导致不处理信号的进程退出。 SOCK_SEQPACKET 套接字使用与 SOCK_STREAM 套接字相同的系统调用。 唯一的区别是 read(2) 调用将只返回请求的数据量,到达数据包中剩余的其他数据都将被丢弃。 传入数据报中的所有消息边界也被保留。
SOCK_DGRAM 和 SOCK_RAW 套接字允许将数据报发送到在 sendto(2) 调用中指定的通信者。 数据报通常用 recvfrom(2) 接收,它返回下一个数据报及其发送者的地址。
SOCK_PACKET 是一种过时的套接字类型,用于直接从设备驱动程序接收原始数据包。 改用 packet(7)。
An fcntl(2) F_SETOWN operation can be used to specify a process or process group to receive a SIGURG signal when the out-of-band data arrives or SIGPIPE signal when a SOCK_STREAM connection breaks unexpectedly. This operation may also be used to set the process or process group that receives the I/O and asynchronous notification of I/O events via SIGIO. Using F_SETOWN is equivalent to an ioctl(2) call with the FIOSETOWN or SIOCSPGRP argument.
When the network signals an error condition to the protocol module (e.g., using an ICMP message for IP) the pending error flag is set for the socket. The next operation on this socket will return the error code of the pending error. For some protocols it is possible to enable a per-socket error queue to retrieve detailed information about the errorsee IP_RECVERR in ip(7).
套接字的 *** 作由套接字选项控制。 这些选项在 <sys/socket.h>中定义。 函数setsockopt(2) 和getsockopt(2) 用于设置和获取选项。对于选项的描述,详见socket(7).
成功时,将返回新套接字的文件描述符。 出错时,返回 -1,并设置 errno 以指示错误。
POSIX.1-2001, POSIX.1-2008, 4.4BSD.
The SOCK_NONBLOCK and SOCK_CLOEXEC flags are Linux-specific.
socket() appeared in 4.2BSD. It is generally portable to/from non-BSD systems supporting clones of the BSD socket layer (including System V variants).
在 4.x BSD 下用于协议族的清单常量是 PF_UNIX、PF_INET 等,而 AF_UNIX、AF_INET 等用于地址族。 但是,BSD 手册页已经承诺:“协议族通常与地址族相同”,随后的标准到处都使用 AF_*。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)