accept_and_recv() — Accept connection and receive first message

Standards

Standards / Extensions C or C++ Dependencies
z/OS® UNIX both  

Format

X/Open:
#define _OPEN_SYS_SOCK_EXT2
#include <sys/socket.h>

int accept_and_recv(int socket, int *accept_socket,
                    struct sockaddr *remote_address,
                    socklen_t *remote_address_len,
                    struct sockaddr *local_address,
                    socklen_t *local_address_len,
                    void *buffer, size_t buffer_len);

General description

The accept_and_recv() function extracts the first connection on the queue of pending connections. It either reuses the specified socket (if *accept_socket is not -1) or creates a new socket with the same socket type, protocol, and address family as the listening socket (if *accept_socket is -1). It then returns the first block of data sent by the peer and returns the local and remote socket addresses associated with the connection.

The function takes the following arguments:
Parameter
Description
socket
Specifies a socket that was created with socket(), has been bound to an address with bind(), and has issued a successful call to listen().
accept_socket
Pointer to an int which specifies the socket on which to accept the incoming connection. The socket must not be bound or connected. Use of this parameter lets the application reuse the accepting socket. It is possible that the system may choose to reuse a different socket than the one the application specified by this argument. In this case, the system will set *accept_socket to the socket actually reused.

A value of -1 for *accept_socket indicates that the accepting socket should be assigned by the system and returned to the application in this parameter. It is recommended that a value of -1 be used on the first call to accept_and_recv(). For more details, see Usage notes.

remote_address
Either a NULL pointer or a pointer to a sockaddr structure where the address of the connecting socket will be returned.
remote_address_len
Points to a socklen_t. On input, this specifies the length of the supplied sockaddr structure. On output, this contains the length of the stored address.
local_address
Either a NULL pointer or a pointer to a sockaddr structure where the address of the local socket will be returned.
local_address_len
Points to a socklen_t. On input, this specifies the length of the supplied sockaddr structure. On output, this contains the length of the stored address.
buffer
Either a NULL pointer, or a pointer to a buffer where the message should be stored. If this is a NULL pointer, no receive is performed, and accept_and_recv() completes when the incoming connection is received.
buffer_len
Specifies the length in bytes of the buffer pointed to by the buffer argument.

If *accept_socket is not -1, the incoming connection will be accepted on the socket specified by *accept_socket. The system may choose to reuse a different socket. If it does, the system will change *accept_socket to reflect the socket actually used.

If remote_address is not a NULL pointer, the address of the peer for the accepted connection is stored in the sockaddr structure pointed to by remote_address, and the length of this address is stored in the object pointed to by remote_address_len. If the actual length of the address is greater than the length of the supplied socket address structure, the stored address will be truncated.

If local_address is not a NULL pointer, the address of the local socket associated with this connection is stored in the sockaddr structure pointed to by local_address, and the length of this address is stored in the object pointed to by local_address_len. If the actual length of the address is greater than the length of the supplied socket address structure, the stored address will be truncated.

Nonblocking mode is not supported for this function. If O_NONBLOCK is set on the socket file descriptor, the function will return with -1 and errno will be set to EOPNOTSUPP.

If the listen queue is empty of connection requests, accept_and_recv() will not return until an incoming connection is received.

If buffer is not NULL, accept_and_recv will not return until the first block of data on the connection has been received, otherwise accept_and_recv() returns 0 after the connection is established.

Note: The accept_and_recv() function has a dependency on the level of the Enhanced ASCII Extensions. See Enhanced ASCII support for details.

Usage notes

  1. On the first call to accept_and_recv(), it is recommended that the application set the socket pointed to by accept_socket to -1. This will cause the system to assign the accepting socket. The application then passes the assigned value into the next call to accept_and_recv() (by setting accept_socket = socket_ptr).

    To take full advantage of the performance improvements offered by the accept_and_recv() function, a process/thread model different from the one where a parent accepts in a loop and spins off child process threads is needed. The parent/process thread is eliminated. Multiple worker processes/threads are created, and each worker process/thread then executes the accept_and_recv() function in a loop. The performance benefits of accept_and_recv() include fewer buffer copies, recycled sockets, and optimal scheduling.

Returned value

If successful, accept_and_recv() returns the number of bytes (zero or more) stored in the buffer pointed to by the buffer argument. Zero can be returned when buffer is NULL or when the client closes the socket without sending any data.

A partial success is achieved with *accept_socket being assigned, a return value of -1 and errno set to one of the following values:

Error Code
Description
EINTRNODATA
The accept_and_recv() function was interrupted by a signal that was caught after a valid connection was established, but before the first block of data arrived.
EWOULDBLOCK
A new connection was established, but the SO_RCVTIMEO timeout value was reached before data was available.

If unsuccessful, accept_and_recv() sets *accepted_socket to -1, returns -1 and sets errno to one of the following values:

Error Code
Description
EBADF
One of two errors occurred:
  1. socket is not a valid descriptor.
  2. accept_socket does not point to a valid descriptor.
ECONNABORTED
A connection has been aborted.
ECONNRESET
A connection was forcibly closed by a peer.
EFAULT
The data buffer pointed to by accept_socket, remote_address, remote_address_len, local_address, local_address_len, or buffer was not valid.
EINTR
The accept_and_recv() function was interrupted by a signal that was caught before a valid connection was established.
EINVAL
The socket is not accepting connections.
EIO
An I/O error occurred.
EISCONN
The accept_socket is either bound or connected already.
EMFILE
OPEN_MAX descriptors are already open in the calling process.
ENOBUFS
No buffer space is available.
ENOMEM
There was insufficient memory available to complete the operation.
ENOREUSE
Socket reuse is not supported.
ENOSR
There were insufficient STREAMS resources available for the operation to complete.
ENOTSOCK
The socket argument does not refer to a socket, or accept_socket does not point to a socket.
EOPNOTSUPP
One of errors occurred:
  1. The type of the socket does not support accepting connections.
  2. O_NONBLOCK is set for the socket and nonblocking is not supported for this function.

Related information