Manpages

NAME 名 称

accept - 在 一 个 套 接 字 上 接 收 一 个 连 接

SYNOPSIS 概 述

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

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

DESCRIPTION 描 述

accept 函 数 用 于 基 于 连 接 的 套 接 字 (SOCK_STREAM, SOCK_SEQPACKETSOCK_RDM). 它 从 未 完 成 连 接 队 列 中 取 出 第 一 个 连 接 请 求 ,创 建 一 个 和 参 数 s 属 性 相 同 的 连 接 套 接 字 ,并 为 这 个 套 接 字 分 配 一 个 文 件 描 述 符 , 然 后 以 这 个 描 述 符 返 回 .新 创 建 的 描 述 符 不 再 处 于 倾 听 状 态 .原 套 接 字 s 不 受 此 调 用 的 影 响 .注 意 任 意 一 个 文 件 描 述 符 标 志 (任 何 可 以 被 fcntl以 参 数 F_SETFL 设 置 的 值 ,比 如 非 阻 塞 式 或 者 异 步 状 态 )不 会 被 accept. 所 继 承 . 参 数 s 是 以 socket(2) 创 建 ,用 bind(2) 绑 定 到 一 个 本 地 地 址 ,并 且 在 调 用 了 listen(2). 之 后 正 在 侦 听 一 个 连 接 的 套 接 字 . 参 数 addr 是 一 个 指 向 结 构 sockaddr的 指 针 .这 个 结 构 体 以 连 接 实 体 地 址 填 充 . 所 谓 的 连 接 实 体 ,就 是 众 所 周 知 的 网 络 层 .参 数 addr 所 传 递 的 真 正 的 地 址 格 式 依 赖 于 所 使 用 的 套 接 字 族 . (参 见 socket(2) 和 各 协 议 自 己 的 手 册 页 ). addrlen 是 一 个 实 时 参 数 : 它 的 大 小 应 该 能 够 足 以 容 纳 参 数 addr 所 指 向 的 结 构 体 ;在 函 数 返 回 时 此 参 数 将 以 字 节 数 表 示 出 返 回 地 址 的 实 际 长 度 .若 addr 使 用 NULL作 为 参 数 ,addrlen将 也 被 置 为 NULL. 如 果 队 列 中 没 有 未 完 成 连 接 套 接 字 ,并 且 套 接 字 没 有 标 记 为 非 阻 塞 式 , accept 将 阻 塞 直 到 一 个 连 接 到 达 .如 果 一 个 套 接 字 被 标 记 为 非 阻 塞 式 而 队 列 中 没 有 未 完 成 连 接 套 接 字 , accept 将 返 回 EAGAIN. 使 用 select(2) 或 者 poll(2). 可 以 在 一 个 套 接 字 上 有 连 接 到 来 时 产 生 事 件 .当 尝 试 一 个 新 的 连 接 时 套 接 字 读 就 绪 ,这 样 我 们 就 可 以 调 用 accept 为 这 个 连 接 获 得 一 个 新 的 套 接 字 .此 外 ,你 还 可 以 设 置 套 接 字 在 唤 醒 时 接 收 到 信 号 SIGIO; 细 节 请 参 见 socket(7) 对 于 那 些 需 要 显 式 确 认 的 协 议 ,比 如 DECNet, accept 可 以 看 作 仅 仅 从 队 列 中 取 出 下 一 个 连 接 而 不 做 确 认 .当 在 这 个 新 的 文 件 描 述 符 上 进 行 普 通 读 写 操 作 时 暗 示 了 确 认 ,当 关 闭 这 个 新 的 套 接 字 时 暗 示 了 拒 绝 .目 前 在 Linux上 只 有 DECNet有 这 样 的 含 义 .

NOTES 注 意

当 接 收 到 一 个 SIGIO 信 号 或 者 select(2)poll(2) 返 回 读 就 绪 并 不 总 是 意 味 着 有 新 连 接 在 等 待 ,因 为 连 接 可 能 在 调 用 accept 之 前 已 经 被 异 步 网 络 错 误 或 者 其 他 线 程 所 移 除 .如 果 发 生 这 种 情 况 , 那 么 调 用 将 阻 塞 并 等 待 下 一 个 连 接 的 到 来 .为 确 保 accept 永 远 不 会 阻 塞 ,传 递 的 套 接 字 s 需 要 置 O_NONBLOCK 标 志 (参 见 socket(7)).

RETURN VALUE 返 回 值

此 调 用 在 发 生 错 误 时 返 回 -1.若 成 功 则 返 回 一 个 非 负 整 数 标 识 这 个 连 接 套 接 字 .

ERROR HANDLING 错 误 处 理

Linux accept 将 一 个 待 处 理 网 络 错 误 代 码 通 过 accept 传 递 给 新 套 接 字 . 这 种 处 理 方 式 有 别 于 其 他 的 BSD套 接 字 实 现 .为 可 靠 操 作 ,应 用 程 序 必 须 在 调 用 accept 之 后 能 够 检 测 这 些 为 协 议 定 义 的 网 络 错 误 ,并 且 以 重 试 解 决 ,就 象 EAGAIN 一 样 .对 于 TCP/IP这 些 网 络 错 误 是 ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, 以 及 ENETUNREACH.

ERRORS 错 误

EAGAIN或 者 EWOULDBLOCK 套 接 字 被 标 记 为 非 阻 塞 ,且 当 前 没 有 可 接 收 的 连 接 .

EBADF 描 述 符 非 法

.

ENOTSOCK 描 述 符 指 向 一 个 文 件 ,而 不 是 一 个 套 接 字 .
EOPNOTSUPP
作 为 参 数 的 套 接 字 不 是 SOCK_STREAM. 类 型

EFAULT 参 数

addr 不 在 用 户 可 写 地 址 空 间 之 内 .

EPERM 防 火 墙

规 则 禁 止 连 接 .

ENOBUFS,ENOMEM 没 有 足 够 内 存 . 这 个 错 误 一 般 来 说 意 味 着 内 存 分 配 受 套 接 字 缓 冲 区 所 限 , 而 不 是 没 有 系 统 内 存 . 另 外 ,新 套 接 字 和 协 议 中 定 义 的 网 络 错 误 也 可 能 被 返 回 . 不 同 的 Linux内 核 也 可 能 返 回 下 列 错 误 EMFILE, EINVAL, ENOSR, ENOBUFS, EPERM, ECONNABORTED, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT, ERESTARTSYS.

CONFORMING TO 兼 容 于

SVr4,4.4BSD( accept 函 数 首 次 出 现 于 BSD 4.2). BSD手 册 页 文 档 定 义 了 五 个 可 能 的 错 误 返 回 值 (EBADF, ENOTSOCK, EOPNOTSUPP, EWOULDBLOCK, EFAULT). SUSv2文 档 的 定 义 是 EAGAIN, EBADF, ECONNABORTED, EFAULT, EINTR, EINVAL, EMFILE, ENFILE, ENOBUFS, ENOMEM, ENOSR, ENOTSOCK, EOPNOTSUPP, EPROTO, EWOULDBLOCK.

Linux accept不 继 承 象 O_NONBLOCK 这 样 的 套 接 字 标 志 . 这 一 点 有 别 于 其 他 的 BSD套 接 字 实 现 . 因 此 ,程 序 应 该 在 accept所 返 回 的 套 接 字 上 设 置 所 有 需 要 的 标 志 .

NOTE 注 意

函 数 accept 的 第 三 个 参 数 原 来 被 声 明 为 ’int *’(在 libc4和 libc5以 及 其 他 很 多 系 统 中 , 比 如 BSD 4.*,SunOS 4, SGI);POSIX 1003.1g草 案 试 图 将 其 改 变 为 ’size_t *’,SunOS 5就 是 这 么 做 的 . 后 来 的 POSIX草 案 和 Single Unix Specification以 及 glibc2使 用 了 ’socklen_t *’. Quoting Linus Torvalds: 引 自 Linus Torvalds (译 注 :这 个 家 伙 就 是 Linux的 创 始 人 ,所 以 我 保 留 了 他 老 人 家 的 原 文 , 仅 将 原 文 大 意 附 后 ): I fails: only italicizes a single line _Any_ sane library _must_ have "socklen_t" be the same size as int. Anything else breaks any BSD socket layer stuff. POSIX initially _did_ make it a size_t, and I (and hopefully others, but obviously not too many) complained to them very loudly indeed. Making it a size_t is completely broken, exactly because size_t very seldom is the same size as "int" on 64-bit architectures, for example. And it _has_ to be the same size as "int" because that’s what the BSD socket interface is. Anyway, the POSIX people eventually got a clue, and created "socklen_t". They shouldn’t have touched it in the first place, but once they did they felt it had to have a named type for some unfathomable reason (probably somebody didn’t like losing face over having done the original stupid thing, so they silently just renamed their blunder). 数 据 类 型 "socklen_t"和 int应 该 具 有 相 同 的 长 度 .否 则 就 会 破 坏 BSD套 接 字 层 的 填 充 .POSIX开 始 的 时 候 用 的 是 size_t, Linus Torvalds(他 希 望 有 更 多 的 人 ,但 显 然 不 是 很 多 ) 努 力 向 他 们 解 释 使 用 size_t是 完 全 错 误 的 ,因 为 在 64位 结 构 中 size_t和 int的 长 度 是 不 一 样 的 ,而 这 个 参 数 (也 就 是 accept函 数 的 第 三 参 数 )的 长 度 必 须 和 int一 致 ,因 为 这 是 BSD套 接 字 接 口 标 准 .最 终 POSIX的 那 帮 家 伙 找 到 了 解 决 的 办 法 ,那 就 是 创 造 了 一 个 新 的 类 型 "socklen_t".Linux Torvalds说 这 是 由 于 他 们 发 现 了 自 己 的 错 误 但 又 不 好 意 思 向 大 家 伙 儿 承 认 ,所 以 另 外 创 造 了 一 个 新 的 数 据 类 型 .

SEE ALSO 参 见

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

[中 文 版 维 护 人 ]

byeyear <love_my_love [AT] 263.net >

[中 文 版 最 新 更 新 ]

2002.01.27

《 中 国 linux论 坛 man手 册 页 翻 译 计 划 》 :

http://cmpp.linuxforum.net

本 页 面 中 文 版 由 中 文 man 手 册 页 计 划 提 供 。 中 文 man 手 册 页 计 划 : https://github.com/man-pages-zh/manpages-zh