socket - Linux 套接字接口
#include <sys/socket.h>
sockfd = socket(int socket_family, int socket_type, int protocol);
本手册页描述了 Linux 网络套接字层用户接口。 套接字是用户进程和内核中网络协议栈之间的统一接口。 协议模块分为协议族(protocol families)(如 AF_INET、AF_IPX 和 AF_PACKET)和套接字类型(socket types)(如 SOCK_STREAM 或 SOCK_DGRAM)。 有关families和types的更多信息,请参阅 socket(2)。
Socket-layer functions
用户进程使用这些函数来发送或接收数据包以及执行其他套接字操作。 有关更多信息,请参阅它们各自的手册页。
socket(2) 创建套接字,connect(2) 将套接字连接到远程套接字地址,bind(2) 函数将套接字绑定到本地套接字地址,listen(2) 告诉套接字应接受新连接, accept(2) 用于获取具有新传入连接的新套接字。 socketpair(2) 返回两个连接的匿名套接字(仅为少数本地families如 AF_UNIX 实现)
send(2)、sendto(2) 和sendmsg(2) 通过套接字发送数据,而recv(2)、recvfrom(2)、recvmsg(2) 从套接字接收数据。 poll(2) 和 select(2) 等待数据到达或准备好发送数据。 此外,还可以使用 write(2)、writev(2)、sendfile(2)、read(2) 和 readv(2) 等标准 I/O 操作来读取和写入数据。
getsockname(2) 返回本地套接字地址, getpeername(2) 返回远程套接字地址。 getsockopt(2) 和 setsockopt(2) 用于设置或获取套接字层或协议选项。 ioctl(2) 可用于设置或读取一些其他选项。
close(2) 用于关闭套接字。 shutdown(2) 关闭全双工套接字连接的一部分。
套接字不支持使用非零位置查找或调用 pread(2) 或 pwrite(2)。
通过使用 fcntl(2) 在套接字文件描述符上设置 O_NONBLOCK 标志,可以在套接字上执行非阻塞 I/O。 然后所有会阻塞的操作(通常)将返回 EAGAIN(操作应稍后重试); connect(2) 将返回 EINPROGRESS 错误。 然后用户可以通过 poll(2) 或 select(2) 等待各种事件。
I/O Event
Event | Poll flag | Occurrence |
---|---|---|
Event | Poll flag | Occurrence |
Read | POLLIN | New data arrived. |
Read | POLLIN | A connection setup has been completed (for connection-oriented sockets) |
Read | POLLHUP | A disconnection request has been initiated by the other end. |
Read | POLLHUP | A connection is broken (only for connection-oriented protocols). When the socket is written SIGPIPE is also sent. |
Write | POLLOUT | Socket has enough send buffer space for writing new data. |
Read/Write | POLLIN |POLLOUT | An outgoing connect(2) finished. |
Read/Write | POLLERR | An asynchronous error occurred. |
Read/Write | POLLHUP | The other end has shut down one direction. |
Exception | POLLPRI | Urgent data arrived. SIGURG is sent then |
如果不使用poll(2) 和 select(2) ,还让内核通过 SIGIO 信号通知应用程序有关事件的信息。 为此,必须通过 fcntl(2) 在套接字文件描述符上设置 O_ASYNC 标志,并且必须通过 sigaction(2) 安装有效的 SIGIO 信号处理程序。 请参阅下面的信号讨论。
Socket address structures
每个套接字域(families)都有自己的套接字地址格式,具有特定于域的地址结构。 这些结构的首字段都是整数类型的“家族”字段(类型为 sa_family_t),即指出自己的套接字域或者说是protocol families。 这允许对所有套接字域可以使用统一的系统调用(例如,connect(2)、bind(2)、accept(2)、getsockname(2)、getpeername(2)),并通过套接字地址来确定特定的域。
为了允许将任何类型的套接字地址传递给套接字 API 中的接口,定义了类型 struct sockaddr。 这种类型的目的纯粹是为了允许将特定于域的套接字地址类型转换为“通用”类型,以避免编译器在调用套接字 API 时发出有关类型不匹配的警告。
struct sockaddr 以及在AF_INET常用的地址结构struct sockaddr_in如下所示,sockaddr_in.sin_zero是占位符:
struct sockaddr
{
sa_family_t sa_family; /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
};
/* Structure describing an Internet socket address. */
struct sockaddr_in
{
sa_family_t sin_family;
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr)
- __SOCKADDR_COMMON_SIZE
- sizeof (in_port_t)
- sizeof (struct in_addr)];
};
/* Ditto, for IPv6. */
struct sockaddr_in6
{
sa_family_t sin6_family;
in_port_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* IPv6 scope-id */
};
/* Structure describing the address of an AF_LOCAL (aka AF_UNIX) socket. */
struct sockaddr_un
{
sa_family_t sun_family;
char sun_path[108]; /* Path name. */
};
此外,套接字 API 提供了数据类型 struct sockaddr_storage。 这种类型适合容纳所有支持的特定于域的套接字地址结构; 它足够大并且正确对齐。 (特别是它足够大,可以容纳 IPv6 套接字地址。)同struct sockaddr一样,该结构体包括以下字段,可用于标识实际存储在结构体中的套接字地址的类型:sa_family_t ss_family;
sockaddr_storage 结构在必须以通用方式处理套接字地址的程序中很有用(例如,必须同时处理 IPv4 和 IPv6 套接字地址的程序)。
Socket options
下面列出的套接字选项可以使用setsockopt(2) 设置并使用getsockopt(2) 读取。
- SO_ACCEPTCONN
- SO_ATTACH_FILTER (Linux 2.2 ), SO_ATTACH_BPF (Linux 3.19)
- SO_ATTACH_REUSEPORT_CBPF, SO_ATTACH_REUSEPORT_EBPF
- SO_BINDTODEVICE
- SO_BROADCAST
- SO_BSDCOMPAT
- SO_DEBUG
- SO_DETACH_FILTER (since Linux 2.2), SO_DETACH_BPF (since Linux 3.19)
- SO_DOMAIN
- SO_ERROR
- SO_DONTROUTE
- SO_INCOMING_CPU
- SO_INCOMING_NAPI_ID
- SO_KEEPALIVE
- SO_LINGER
- SO_LOCK_FILTER
- SO_MARK
- SO_OOBINLINE
- SO_PASSCRED
- SO_PASSSEC
- SO_PEEK_OFF
- SO_PEERCRED
- SO_PEERSEC
- SO_PRIORITY
- SO_PROTOCOL
- SO_RCVBUF
- SO_RCVBUFFORCE
- SO_RCVLOWAT and SO_SNDLOWAT
- SO_REUSEADDR
-
SO_REUSEPORT
参考SO_REUSEADDR和SO_REUSEPORT作用 - SO_RXQ_OVFL
- SO_SELECT_ERR_QUEUE
- SO_SNDBUF
- SO_SNDBUFFORCE
- SO_TIMESTAMP
- SO_TIMESTAMPNS
- SO_TYPE
- SO_BUSY_POLL
Signals
当写入已关闭(由本地或远程端)的面向连接的套接字时,SIGPIPE 被发送到写入进程并返回 EPIPE。 当写调用指定 MSG_NOSIGNAL 标志时,不发送信号。
当使用 FIOSETOWN fcntl(2) 或 SIOCSPGRP ioctl(2) 请求时,会在 I/O 事件发生时发送 SIGIO。 可以在信号处理程序中使用 poll(2) 或 select(2) 来找出事件发生在哪个套接字上。 另一种方法(在 Linux 2.2 中)是使用 F_SETSIG fcntl(2) 设置实时信号; 实时信号的处理程序将使用其 siginfo_t 的 si_fd 字段中的文件描述符调用。 有关更多信息,请参阅 fcntl(2)。
在某些情况下(例如,多个进程访问单个套接字),当进程对信号做出反应时,导致 SIGIO 的条件可能已经消失。 如果发生这种情况,进程应该再次等待,因为 Linux 稍后会重新发送信号。
/proc interfaces
核心套接字网络参数可以通过目录 /proc/sys/net/core/ 中的文件访问。
-
rmem_default
套接字接收缓冲区的默认设置(以字节为单位)。 -
rmem_max
用户可以使用 SO_RCVBUF 套接字选项设置的最大套接字接收缓冲区大小(以字节为单位)。 -
wmem_default
套接字发送缓冲区的默认设置(以字节为单位)。 -
wmem_max
用户可以使用 SO_SNDBUF 套接字选项设置的最大套接字发送缓冲区大小(以字节为单位) -
message_cost
andmessage_cost
configure the token bucket filter used to load limit warning messages caused by external network events. -
netdev_max_backlog
全局输入队列中的最大数据包数。 -
optmem_max
Maximum length of ancillary data and user control data like the iovecs per socket.
Ioctls
These operations can be accessed using ioctl(2):
error = ioctl(ip_socket, ioctl_type, &value_result);
-
SIOCGSTAMP
Return a struct timeval with the receive timestamp of the last packet passed to the user. This is useful for accurate round trip time measurements. See setitimer(2) for a description of struct timeval. This ioctl should be used only if the socket options SO_TIMESTAMP and SO_TIMESTAMPNS are not set on the socket. Otherwise, it returns the timestamp of the last packet that was received while SO_TIMESTAMP and SO_TIMESTAMPNS were not set, or it fails if no such packet has been received, (i.e., ioctl(2) returns -1 with errno set to ENOENT). -
SIOCSPGRP
Set the process or process group that is to receive SIGIO or SIGURG signals when I/O becomes possible or urgent data is available. The argument is a pointer to a pid_t. For further details, see the description of F_SETOWN in fcntl(2). -
FIOASYNC
Change the O_ASYNC flag to enable or disable asynchronous I/O mode of the socket. Asynchronous I/O mode means that the SIGIO signal or the signal set with F_SETSIG is raised when a new I/O event occurs.
Argument is an integer boolean flag. (This operation is synonymous with the use of fcntl(2) to set the O_ASYNC flag.) -
SIOCGPGRP
Get the current process or process group that receives SIGIO or SIGURG signals, or 0 when none is set.
Valid fcntl(2) operations:
-
FIOGETOWN
The same as the SIOCGPGRP ioctl(2). -
FIOSETOWN
The same as the SIOCSPGRP ioctl(2).
SO_BINDTODEVICE 是在 Linux 2.0.30 中引入的。 SO_PASSCRED 是 Linux 2.2 中的新功能。 /proc 接口是在 Linux 2.2 中引入的。 从 Linux 2.3.41 开始支持 SO_RCVTIMEO 和 SO_SNDTIMEO。 早些时候,超时被固定为特定于协议的设置,并且无法读取或写入。
Linux assumes that half of the send/receive buffer is used for internal kernel structures; thus the values in the corresponding /proc files are twice what can be observed on the wire. Linux will allow port reuse only with the SO_REUSEADDR option when this option was set both in the previous program that performed a bind(2) to the port and in the program that wants to reuse the port. This differs from some implementations (e.g., FreeBSD) where only the later program needs to set the SO_REUSEADDR option. Typically this difference is invisible, since, for example, a server program is designed to always set this option.
网友评论