文章目录

  • 名称
  • 使用格式
  • 功能参数描述
  • 参数
    • sockfd
    • addr
    • addrlen
  • 返回值
  • 示例
  • man 2 文档中的accept解释
  • 错误处理

名称

accept()

接收一个套接字中已建立的连接

使用格式

#include <sys/types.h>#include <sys/socket.h>int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

功能参数描述

accept()系统调用主要用在基于连接的套接字类型,比如SOCK_STREAM和SOCK_SEQPACKET。它提取出所监听套接字的等待连接队列中第一个连接请求,创建一个新的套接字,并返回指向该套接字的文件描述符。新建立的套接字不在监听状态,原来所监听的套接字也不受该系统调用的影响。

备注:新建立的套接字准备发送send()和接收数据recv()。

参数

sockfd

利用系统调用socket()建立的套接字描述符,通过bind()绑定到一个本地地址(一般为服务器的套接字),并且通过listen()一直在监听连接;

addr

指向struct sockaddr的指针,该结构用通讯层服务器对等套接字的地址(一般为客户端地址)填写,返回地址addr的确切格式由套接字的地址类别(比如TCP或UDP)决定;若addr为NULL,没有有效地址填写,这种情况下,addrlen也不使用,应该置为NULL;

备注:addr是个指向局部数据结构sockaddr_in的指针,这就是要求接入的信息本地的套接字(地址和指针)。

addrlen

一个值结果参数,调用函数必须初始化为包含addr所指向结构大小的数值,函数返回时包含对等地址(一般为服务器地址)的实际数值;

备注:addrlen是个局部整形变量,设置为sizeof(struct sockaddr_in)。

如果队列中没有等待的连接,套接字也没有被标记为Non-blocking,accept()会阻塞调用函数直到连接出现;如果套接字被标记为Non-blocking,队列中也没有等待的连接,accept()返回错误EAGAIN或EWOULDBLOCK。

备注:一般来说,实现时accept()为阻塞函数,当监听socket调用accept()时,它先到自己的receive_buf中查看是否有连接数据包;

若有,把数据拷贝出来,删掉接收到的数据包,创建新的socket与客户发来的地址建立连接;

若没有,就阻塞等待;

为了在套接字中有到来的连接时得到通知,可以使用select()或poll()。当尝试建立新连接时,系统发送一个可读事件,然后调用accept()为该连接获取套接字。另一种方法是,当套接字中有连接到来时设定套接字发送SIGIO信号。

返回值

成功时,返回非负整数,该整数是接收到套接字的描述符;出错时,返回-1,相应地设定全局变量errno。

示例

    while (1) {if ((connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1) {     //传NULL什么意思?printf("accept socket error: %s(errno: %d)", strerror(errno), errno);continue;}n = recv(connfd, buff, MAXLINE, 0);buff[n] = '\0';printf("recv msg from client: %s\n", buff);close(connfd);}

man 2 文档中的accept解释

ACCEPT(2)                                                            Linux Programmer's Manual                                                           ACCEPT(2)NAMEaccept, accept4 - accept a connection on a socket //接受套接字上的连接SYNOPSIS#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);#define _GNU_SOURCE             /* See feature_test_macros(7) */#include <sys/socket.h>int accept4(int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags);DESCRIPTIONThe  accept()  system call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET).  It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that  socket.   The newly created socket is not in the listening state.  The original socket sockfd is unaffected by this call.//accept() 系统调用与基于连接的套接字类型(SOCK_STREAM、SOCK_SEQPACKET)一起使用。 它为侦听套接字提取挂起连接队列中的第一个连接请求,sockfd,创建一个新的连接套接字,并返回一个引用该套接字的新文件描述符。 新创建的套接字不处于监听状态。 原始套接字 sockfd 不受此调用的影响。The  argument sockfd is a socket that has been created with socket(2), bound to a local address with bind(2), and is listening for connections after a listen(2).//参数 sockfd 是一个使用 socket(2) 创建的套接字,使用 bind(2) 绑定到本地地址,并在 listen(2) 之后侦听连接。The argument addr is a pointer to a sockaddr structure.  This structure is filled in with the address of the peer socket, as known  to  the  communications layer.   The  exact format of the address returned addr is determined by the socket's address family (see socket(2) and the respective protocol man pages).When addr is NULL, nothing is filled in; in this case, addrlen is not used, and should also be NULL.//参数 addr 是指向 sockaddr 结构的指针。 如通信层所知,该结构用对等套接字的地址填充。 返回地址 addr 的确切格式由套接字的地址族确定(参见 socket(2) 和相应的协议手册页)。//addr为NULL时,不填任何内容; 在这种情况下,不使用 addrlen,也应该为 NULL。The addrlen argument is a value-result argument: the caller must initialize it to contain the size (in bytes) of the  structure  pointed  to  by  addr;  on return it will contain the actual size of the peer address.//addrlen 参数是一个值结果参数:调用者必须将其初始化为包含 addr 指向的结构的大小(以字节为单位); 返回时它将包含对等地址的实际大小。The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call.//如果提供的缓冲区太小,返回的地址会被截断; 在这种情况下,addrlen 将返回一个大于提供给调用的值。If  no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present.If the socket is marked nonblocking and no pending connections are present on the queue, accept() fails with the error EAGAIN or EWOULDBLOCK.//如果队列中没有挂起的连接,并且套接字没有被标记为非阻塞,accept() 会阻塞调用者,直到连接出现。//如果套接字被标记为非阻塞并且队列中没有挂起的连接,accept() 将失败并返回 EAGAIN 或 EWOULDBLOCK 错误。In order to be notified of incoming connections on a socket, you can use select(2) or poll(2).  A readable event will be delivered when a new connection is attempted  and you may then call accept() to get a socket for that connection.  Alternatively, you can set the socket to deliver SIGIO when activity occurs on a socket; see socket(7) for details.//为了通知套接字上的传入连接,您可以使用 select(2) 或 poll(2)。 尝试新连接时将传递一个可读事件,然后您可以调用 accept() 以获取该连接的套接字。 或者,您可以将套接字设置为在套接字上发生活动时传递 SIGIO; 有关详细信息,请参阅套接字(7)。For certain protocols which require an explicit confirmation, such as DECNet, accept() can be thought of as merely dequeuing the  next  connection  request and  not  implying confirmation.  Confirmation can be implied by a normal read or write on the new file descriptor, and rejection can be implied by closing the new socket.  Currently only DECNet has these semantics on Linux.//对于某些需要显式确认的协议,例如 DECNet,accept() 可以被认为只是将下一个连接请求出队而不是暗示确认。 对新文件描述符的正常读取或写入可以暗示确认,并且可以通过关闭新套接字来暗示拒绝。 目前只有 DECNet 在 Linux 上具有这些语义。If flags is 0, then accept4() is the same as accept().  The following values can be bitwise ORed in flags to obtain different behavior://如果 flags 为 0,则 accept4() 与 accept() 相同。 可以在标志中对以下值进行按位或运算以获得不同的行为:SOCK_NONBLOCK   Set the O_NONBLOCK file status flag on the new open file description.  Using this flag saves extra calls to fcntl(2) to  achieve  the  same result.SOCK_CLOEXEC    Set  the  close-on-exec (FD_CLOEXEC) flag on the new file descriptor.  See the description of the O_CLOEXEC flag in open(2) for reasons whythis may be useful.RETURN VALUEOn success, these system calls return a nonnegative integer that is a descriptor for the accepted socket.  On error, -1  is  returned,  and  errno  is  setappropriately.Error handlingLinux  accept()  (and  accept4()) passes already-pending network errors on the new socket as an error code from accept().  This behavior differs from other BSD socket implementations.  For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying.  In the case of TCP/IP, these are ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH.//Linux accept()(和 accept4())将新套接字上已经挂起的网络错误作为来自 accept() 的错误代码传递。 此行为不同于其他 BSD 套接字实现。 为了可靠运行,应用程序应该在 accept() 之后检测为协议定义的网络错误,并通过重试将它们视为 EAGAIN。 对于 TCP/IP,它们是 ENETDOWN、EPROTO、ENOPROTOOPT、EHOSTDOWN、ENONET、EHOSTUNREACH、EOPNOTSUPP 和 ENETUNREACH。ERRORSEAGAIN or EWOULDBLOCKThe socket is marked nonblocking and no connections are present to be accepted.  POSIX.1-2001 and POSIX.1-2008 allow either error to be returned forthis case, and do not require these constants to have the same value, so a portable application should check for both possibilities.EBADF  The descriptor is invalid.ECONNABORTEDA connection has been aborted.EFAULT The addr argument is not in a writable part of the user address space.EINTR  The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).EINVAL Socket is not listening for connections, or addrlen is invalid (e.g., is negative).EINVAL (accept4()) invalid value in flags.EMFILE The per-process limit on the number of open file descriptors has been reached.ENFILE The system-wide limit on the total number of open files has been reached.ENOBUFS, ENOMEMNot enough free memory.  This often means that the memory allocation is limited by the socket buffer limits, not by the system memory.ENOTSOCKThe file descriptor sockfd does not refer to a socket.EOPNOTSUPPThe referenced socket is not of type SOCK_STREAM.EPROTO Protocol error.In addition, Linux accept() may fail if:EPERM  Firewall rules forbid connection.In addition, network errors for the new socket and as defined for the protocol may be returned.  Various Linux kernels can  return  other  errors  such  asENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT.  The value ERESTARTSYS may be seen during a trace.VERSIONSThe accept4() system call is available starting with Linux 2.6.28; support in glibc is available starting with version 2.10.CONFORMING TOaccept(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (accept() first appeared in 4.2BSD).accept4() is a nonstandard Linux extension.On  Linux,  the new socket returned by accept() does not inherit file status flags such as O_NONBLOCK and O_ASYNC from the listening socket.  This behaviordiffers from the canonical BSD sockets implementation.  Portable programs should not rely on inheritance or noninheritance of file status flags and  alwaysexplicitly set all required flags on the socket returned from accept().NOTESPOSIX.1-2001  does  not  require the inclusion of <sys/types.h>, and this header file is not required on Linux.  However, some historical (BSD) implementa‐tions required this header file, and portable applications are probably wise to include it.There may not always be a connection waiting after a SIGIO is delivered or select(2) or poll(2) return a readability event  because  the  connection  might have  been removed by an asynchronous network error or another thread before accept() is called.  If this happens, then the call will block waiting for the next connection to arrive.  To ensure that accept() never blocks, the passed socket sockfd needs to have the O_NONBLOCK flag set (see socket(7)).//在传递 SIGIO 或 select(2) 或 poll(2) 返回可读性事件之后,可能并不总是有连接等待,因为在调用 accept() 之前,连接可能已被异步网络错误或另一个线程删除。 如果发生这种情况,则调用将阻塞等待下一个连接到达。 为了确保 accept() 永远不会阻塞,传递的套接字 sockfd 需要设置 O_NONBLOCK 标志(参见 socket(7))。The socklen_t typeThe third argument of accept() was originally declared as an int * (and is that under libc4 and libc5 and on many other systems  like  4.x  BSD,  SunOS  4,SGI);  a  POSIX.1g  draft standard wanted to change it into a size_t *, and that is what it is for SunOS 5.  Later POSIX drafts have socklen_t *, and so dothe Single UNIX Specification and glibc2.  Quoting Linus Torvalds:"_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  asize_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, exactlybecause 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 theBSD  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, butonce 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  originalstupid thing, so they silently just renamed their blunder)."EXAMPLESee bind(2).SEE ALSObind(2), connect(2), listen(2), select(2), socket(2), socket(7)COLOPHONThis  page  is part of release 4.04 of the Linux man-pages project.  A description of the project, information about reporting bugs, and the latest versionof this page, can be found at http://www.kernel.org/doc/man-pages/.Linux                                                                       2015-12-28                                                                   ACCEPT(2)Manual page accept(2) line 104/145 (END) (press h for help or q to quit)

错误处理

Linux下,accept()把已等待的网络错误传给新建立的连接,当作是accept()返回的错误。这于其他的BSD实现是不同的。为了可靠运行,应该在accept()之后检测协议已定义的一些网络错误,并把这些错误当作EAGAIN并重试。对于TCP/IP协议来说,主要有错误:ENETDOWN,EPROTO,ENOPROTOOPT,EHOSTDOWN,ENONET,EHOSTUNREACH,EOPNOTSUPP和ENETUNREACH。

参考文章1:socket编程之accept()函数

参考文章2:linux C语言 socket编程教程(附两个例子)

C语言socket accept()函数(提取出所监听套接字的等待连接队列中第一个连接请求,创建一个新的套接字,并返回指向该套接字的文件描述符)相关推荐

  1. 文件句柄?文件描述符?傻傻分不清楚

    概述 在实际工作中会经常遇到一些bug,有些就需要用到文件句柄,文件描述符等概念,比如报错: too many open files, 如果你对相关知识一无所知,那么debug起来将会异常痛苦.在li ...

  2. 020303阶段三 I/O复用 select和epoll的文件描述符管理

    目录 一.学习的知识点 1 五种 I/O 1.1 阻塞式I/O 1.2 非阻塞式I/O 1.3 I/O复用(select 和pool) 1.3.1 select 文件描述符的管理 select 缺点 ...

  3. 文件句柄(file handles) 文件描述符(file descriptors)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  4. 【C/C++服务器开发】文件,文件描述符,I/O多路复用,select / poll / epoll 详解

    文章目录 一.前言 1.文件的概念 2.文件描述符和文件指针 文件描述符 文件描述符和文件指针的区别 文件描述符太多了怎么办 二.I/O多路复用 1.I/O多路复用的由来 不要打电话给我,有需要我会打 ...

  5. 一文帮你搞懂 Android 文件描述符

    介绍文件描述符的概念以及工作原理,并通过源码了解 Android 中常见的 FD 泄漏. 一.什么是文件描述符? 文件描述符是在 Linux 文件系统的被使用,由于Android基 于Linux 系统 ...

  6. linux进程文件描述符 vnode,Linux C编程详解:进程原理分析、文件描述符和文件记录表、文件句柄和文件原理...

    一.引言 文件操作是Linux C编程中其中的一项核心技术,实际上也相当重要,这里并不是说狭义上的那种文件操作,它也非常有助于理解和学习Linux系统.为什么这样说呢?因为在Unix/Linux的世界 ...

  7. Linux文件,文件描述符以及dup()和dup2()

    一.Linux中文件 可以分为4种:普通文件.目录文件.链接文件和设备文件. 1.普通文件 是用户日常使用最多的文件,包括文本文件.shell脚本.二进制的可执行和各种类型的数据. ls -lh 来查 ...

  8. 服务器文件描述,服务器编程中的文件描述符

    Linux系统下一切皆文件,通过虚拟文件系统(VFS)的机制将所有底层屏蔽掉,用户可以通过统一的接口来实现对不同驱动的操作,对于每一个文件需要一个引用来指示,此时文件描述符应用而生,文件描述符类似于W ...

  9. linux存储--文件描述符fd与FILE结构体(二)

    文件描述符fd 对于linux而言,所有对设备(对于linux而言,一切皆文件)和文件的操作都使用文件描述符来进行的. 文件描述符是一个非负的整数,它是一个索引值,指向内核中每个进程打开文件的记录表. ...

最新文章

  1. python编程入门教学下载-Python编程从入门到实践的PDF教程免费下载
  2. 开机logo切换逻辑深入研究
  3. 虚函数与纯虚函数的区别
  4. python之Queue
  5. C#用Zlib压缩或解压缩字节数组
  6. linux设备驱动之 i2c设备驱动 at24c08驱动程序分析【全部地址的操作】
  7. 为何电脑上不显示手机连接服务器,为什么我电脑都能连接上vpn手机却连不上
  8. 用两个半图片来看图片
  9. win10虚拟机dhcp服务器,怎么解决win10系统关闭虚拟机开机停在dhcp无法启动的问题...
  10. unity 回车_Unity InputField空格引起排版错误和回车换行
  11. java求拼接后的字符串长度,java如何拼接字符串
  12. Rockchip Linux CMA开发文档
  13. mysql统计一年中每周的数据,week(时间)和week(时间,1)不同
  14. Flink-----Flink CDC 实现数据实时同步
  15. 一个测试人员的工作该怎么开展
  16. “¥” 人民币符号及其他币种键盘快捷键
  17. linux shell脚本 nohup,linux真正使用shell脚本做定时任务 关键的Nohup
  18. 移动端H5页面,上下滑动翻页
  19. A+成绩入选纳斯达克100指数 中国版DocuSign何时诞生?
  20. 第一个ios应用(1)

热门文章

  1. 编程的一些快捷键(转帖)
  2. C# 调用SQL的存储过程的接口及实现
  3. Hsiaoyang: Google与站点地图Sitemap
  4. 【推荐】有趣儿的PHP文件操作常用函数总结
  5. ★ 让你的虚机飞起来 ★
  6. java build返回空值_将来与Flutter中的FutureBuilder一起返回null
  7. itextpdf 生成word显示不全_Word经常遇到这些偏僻小问题,值的收藏
  8. python爬虫知识_Python 爬虫技术分享
  9. 冬天到了:你检查过你的防冻液了吗!
  10. 对于按成本组件结构(要素)还原