前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ACCEPT()和ACCEPT4()

ACCEPT()和ACCEPT4()

作者头像
Java架构师必看
发布2021-03-22 15:28:31
发布2021-03-22 15:28:31
1.9K00
代码可运行
举报
文章被收录于专栏:Java架构师必看Java架构师必看
运行总次数:0
代码可运行

名字

accept - 通过套接口接受一个连接

概要

代码语言:javascript
代码运行次数:0
运行
复制
#include Esys/types.h> /* 参看 “注意小节” */
#include Esys/socket.h>

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

#define _GNU_SOURCE /* 参考 feature_test_macros(7) */
#include <sys/socket.h>

int accept4(int sockfd, struct sockaddr *addr,
 socklen_t *addrlen, int flags);

描述

accept() 系统调用应用于可连接套接口类型 ( SOCK_STREAM, SOCK_SEQPACKET)。它取出在监听套接口 sockfd请求队列里的第一个连接,新建一个已连接的套接口,并且返回一个引用该套接口新的文件描述符。新建的套接口不处于监听状态。原始的套接口 sockfd 没有受到影响。

参数 sockfd 是一个由 socket(2) 创建的套接口,通过 bind绑定到一个本地地址,并且在调用 listen(2)之后正处于监听之中。

参数 addr 是指向一个 sockaddr结构的指针。这结构体被填充为一个端套接口,又被称为通信层。返回的地址结体 addr的额外的格式可以通过套接口地址族(参看 socket(2)和各自的协议手册页)来确定。当 addr 是 NULL 时,没有内容被填充,此时 addrlen不被使用,同时也可以是 NULL。

参数 addrlen 是一个“值-返回”型参数,调用者必须把它初始化为 addr指向的结构的大小(字节数),返回时,它指出端地址的实际大小。

如果提供的缓冲区太小,返回的地址将被截断,此时,addrlen 将返回一个比传入更大的值。

如果队列里没有未处理的连接,并且套接口没有标记为不阻塞,accept()会阻塞当前调用进程直到有一个连接出现。如果没有未处理的连接,同时套接口被标记为不阻塞,accept() 返回EAGAINEWOULDBLOCK 错误。

为了在一个套接口有连接时收到通知,你可以使用 select(2) 或 poll(2)。当有连接时,一个可读事件被递送。进一步,你可以设置当一个套接口可用时,发送一个SIGIO,参看 socket(7)来详细了解。

对于一些需要显示验证的协议,比如说 DECNet,accept()只是从队列里取出连接请求,并没有执行验证。验证将在下次对新建的文件描述符进行正常的读或写时进行,并且拒绝可以通过关闭那个新建的套接口来进行。目前在Linux 中只有 DECNet 有如此语义。

flags 是 0,那么 accept4() 与 accept() 功能一样。下面flags 的值可能通过位求或运算来得到不同的行为:

SOCK_NONBLOCK 在新打开的文件描述符设置

O_NONBLOCK 标记。在

fcntl(2) 中保存这个标记可以得到相同的效果。 SOCK_CLOEXEC 在新打开的文件描述符里设置 close-on-exec (

FD_CLOEXEC) 标记。参看在

open(2) 里关于

O_CLOEXEC标记的描述来了解这为什么有用。

返回值

成功时,这个系统调用返回一个非负整数的文件描述符来代表接受的套接口。错误时,返回 -1,并把 errno设置为合适的值。

错误处理

在 Linux 里, accept() (和 accept4()) 把本属于accept() 的但未处理的网络错误传递给新建的套接口。 这个行为不同于其它 BSD 的实现。 可靠的应用应该在调用 accept() 之后检测相应协议可能的网络错误,并且处理 EAGAIN 一样重试一次。对于 TCP/IP来说,这些错误有 ENETDOWNEPROTOENOPROTOOPTEHOSTDOWNENONETEHOSTUNREACHEOPNOTSUPPENETUNREACH

错误

EAGAIN

EWOULDBLOCK 套接口被标记为非阻塞并且没有连接等待接受。POSIX.1-2001允许在此时返回这两种错误,但没有要求两个常量必须具有相同的值,所以可移植的程序应该同时检查两者。 EBADF 描述符无效。 ECONNABORTED 一个连接已经中止了。 EFAULT 参数

addr 不在可写的用户地址空间里。 EINTR 在一个有效的连接到达之前,本系统调用被信号中断,参看

signal(7)。 EINVAL 套接口不在监听连接,或

addrlen 无效(如是负数)。 EINVAL (

accept4()) 在

flags 中有无效的值。 EMFILE 达到单个进程打开的文件描述上限。 ENFILE 达到系统允许打开文件个数的全局上限。ENOBUFS,

ENOMEM 没有足够的自由内存。这通常是指套接口内存分配被限制,而不是指系统内存不足。 ENOTSOCK 描述符是一个文件,不是一个套接字。 EOPNOTSUPP 引用的套接口不是

SOCK_STREAM 类型的。 EPROTO 协议错误。

此外,Linux 下的 accept() 可能因如下原因失败:

EPERM 防火墙规则禁止连接。

还有,新建套接口和协议相关的网络错误也可能被返回。多种 Linux 内核还会返回诸如ENOSRESOCKTNOSUPPORTEPROTONOSUPPORTETIMEDOUT的错误。ERESTARTSYS 的值也可能需要关注。

版本

accept4() 系统调用从 Linux 2.6.28 开始支持,glibc 在版本 2.10 开始支持。

遵循于

accept():POSIX.1-2001, SVr4, 4.4BSD, ( accept() 首次出现在4.2BSD)。

accept4() 是非标准 Linux 扩展。

在 Linux 系统里,accept() 返回的新建的套接口 不会 继承监听套接口的诸如O_NONBLOCKO_ASYNC 这样的文件状态。这个行为与正规的 BSD套接口实现不一致。可移植的程序不应该假设文件状态是继承或不继承的,总是显示地设置 accept()返回的套接口需要的标记位。

注意

POSIX.1-2001 不要求包含 <sys/types.h>,并且这个头文件在 Linux中也不要求。然而一些历史(BSD)实现要求这个头文件,可移植的应用程序应该包含这个文件。

SIGIO 递送之后,在 select(2) 或 poll(2) 返回但连接却因为一个异步网络错误而删除之后,或在其它线程调用accept() 之前,不需要总是等待。如果这些事发生了,调用将被阻塞到一个新连接到来,为了让accept() 绝不阻塞,传入的 sockfd 需要设置 O_NONBLOCK 标记(参看socket(7))。

socklen_t 类型

accept() 的第三个参数最初被声明为 int* (在 libc4 和 libc5,以及一些诸如4.x BSD、SunOS4、SGI)。POSIX.1g 草案想把它改为 size_t *,这与SunOS 5是一样的,接着 POSIX 草案提出了 socklen_t *,并且在 Single UnixSpecification 和 glibc2 也是如此。Linus Torvalds 曾说:

“任何合理的库都必须保证 socklen_t 与 int 有相同的长度。否则的话都会与 BSD 套接口不同。POSIX 最初把它定义 为 size_t ,而我(同时也希望其他人,但显然不是太多)对他们表示强烈的不赞同。把它定义为 size_t将是完全地不兼容,尤其在 64 位系统里,size_t 很少跟 int 有相同的宽度。它 必须 与 int有相同的宽度,因为 BSD 接口是这样的。无论如何,制定 POSIX 的人还是创造出 socklen_t了。他们最初不应该去碰这个东西,但是一旦他们碰了,变会因为一些深奥的原因提供一个命名的类型(可能有些人因为之前愚笨的行为而丢脸时,就会静悄悄地他们的行为换个名字)。”

示例

参考 bind(2)。

参看

bind(2), connect(2), listen(2), select(2), socket(2), socket(7)

英文原版:http://man7.org/linux/man-pages/dir_all_alphabetic.html

本文由来源 21aspnet,由 javajgs_com 整理编辑,其版权均为 21aspnet 所有,文章内容系作者个人观点,不代表 Java架构师必看 对观点赞同或支持。如需转载,请注明文章来源。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概要
  • 描述
  • 返回值
    • 错误处理
  • 错误
  • 版本
  • 遵循于
  • 注意
    • socklen_t 类型
  • 示例
  • 参看
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档