accept函数详解

       既然服务端已经很虔诚了,很真诚了,处于倾听状态,那么该是去尝试接受客户端请求的时候了,别只顾着倾听,不去接纳别人。

       接纳客户端请求的函数是accept, 我们先来看看函数的原型:

WINSOCK_API_LINKAGE
SOCKET
WSAAPI
accept(
    SOCKET s,
    struct sockaddr FAR * addr,
    int FAR * addrlen
    );

        函数的第一个参数用来标识服务端套接字(也就是listen函数中设置为监听状态的套接字),第二个参数是用来保存客户端套接字对应的“地方”(包括客户端IP和端口信息等), 第三个参数是“地方”的占地大小。返回值对应客户端套接字标识。

 

        实际上是这样的: accept函数指定服务端去接受客户端的连接,接收后,返回了客户端套接字的标识,且获得了客户端套接字的“地方”(包括客户端IP和端口信息等)。

 

       accept函数非常地痴情,痴心不改:

       如果没有客户端套接字去请求,它便会在那里一直痴痴地等下去,直到永远(注意, 此处讨论的是阻塞式的socket.  如果是非阻塞式的socket, 那么accept函数就没那么痴情了, 而是会立即返回, 并意犹未尽地对未来的客户端扔下一句话: 我等了你, 你不来, 那就算了, 我懒得鸟你)。

 

        来看看accpt函数的用法:

        unsigned int sockConn = accept(sockSrv,(SOCKADDR*)&addrClient, &len);

 

        要睡觉了。睡觉之前,最后来看看linux中的accept:

ubuntu@VM-0-15-ubuntu:~$ man accept
ACCEPT(2)                                     Linux Programmer's Manual                                    ACCEPT(2)

NAME
       accept, 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);

DESCRIPTION
       The  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 cre[m
       ated socket is not in the listening state.  The original socket sockfd is unaffected by this call.

       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).

       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  deter[m
       mined  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.

       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.

       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.

       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 connec[m
       tions are present on the queue, accept() fails with the error EAGAIN or 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.

       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.

       If flags is 0, then accept4() is the same as accept().  The following values can be bitwise ORed in flags  to
       obtain different behavior:

       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 why this may be useful.

RETURN VALUE
       On success, these system calls return a nonnegative integer that is a descriptor for the accepted socket.  On
       error, -1 is returned, and errno is set appropriately.

   Error handling
       Linux 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 applica[m
       tion 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.

ERRORS
       EAGAIN or EWOULDBLOCK
              The 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 for this 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.

       ECONNABORTED
              A 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.

......

         

          睡觉。

 


 

评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值