ACCEPT 和ACCEPT4

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

ACCEPT

章节:Linux 程序员手册 (2)
更新:2010-09-10

易美翻译 翻译

名字

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

概要

#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

错误

EAGAINEWOULDBLOCK
套接口被标记为非阻塞并且没有连接等待接受。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


           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/gdfjhc/article/details/83934783
今日推荐