Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
SCTP Programmer's Guide: HP-UX 11i v2, HP-UX 11i v3 > Chapter 2 SCTP Socket APIs

Different Socket API Styles

» 

Technical documentation

» Feedback
Content starts here

 » Table of Contents

 » Glossary

 » Index

This section discusses the different socket API styles and the basic call flow sequence of each socket API style.

Following are the different socket API styles:

  • One-to-one socket APIs

  • One-to-many socket APIs

The one-to-one style API is similar to the existing socket APIs for a connection-oriented protocol, such as TCP. The one-to-many style API facilitates simultaneous associations with multiple peers using one end point (that is, it associates with multiple peers using one socket file descriptor simultaneously).

These socket API styles share common data structures and operations. However, each socket API style requires a different application programming style. You can use these socket APIs to implement all the SCTP features. You can also select the API style depending on the type of association you need in the application.

This section addresses the following topics:

One-to-One Socket APIs

The one-to-one style socket APIs are designed to enable the existing TCP applications to migrate to SCTP with minimal changes. The sequence of socket calls made by the client and server of a one-to-one style SCTP application is similar to the sequence of socket calls made by a TCP application. A one-to-one style SCTP application can control only one association using one file descriptor.

Basic One-to-One Call Flow Sequence

A one-to-one style SCTP application uses the following system call sequence to prepare an SCTP endpoint for servicing requests:

  1. socket()()

  2. bind()() or sctp_bindx()()

  3. sctp_getladdrs()()

  4. sctp_freeladdrs()

  5. listen()()

  6. accept()()

    When a client sends a connection request to the server, the accept()() call returns with a new socket descriptor. The server then uses the new socket descriptor to communicate with the client, using recv()() and send()() calls to receive requests and send responses.

  7. sctp_getpaddrs()()

  8. sctp_freepaddrs()

  9. recv()() or recvmsg()()

  10. send()() or sctp_sendx()() or sctp_send()()

  11. close()() terminates the association.

An SCTP client uses the following system call sequence to set up an association with a server to request services:

  1. socket()()

  2. connect()() or sctp_connectx()()

    After returning from connect()(), the client uses send()() and recv()() calls to send out requests and receive responses from the server.

  3. The client calls close()() to terminate this association when .

For more information about the one-to-one style socket calls, see“Common Socket Calls”.

The socket() Socket API

Applications call socket()() to create a socket descriptor, to represent an SCTP endpoint.

Following is the syntax for the socket()() socket API:

int socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);

or

int socket(PF_INET6, SOCK_STREAM, IPPROTO_SCTP);

where:

PF_INET

Specifies the IPv4 domain.

PF_INET6

Specifies the IPv6 domain.

SOCK_STREAM

Indicates the creation of a one-to-one style socket.

IPPROTO_SCTP

Specifies the type of the protocol.

The first syntax of the socket()() socket API creates an endpoint that can use only IPv4 addresses, while the second syntax creates an endpoint, which can use both IPv6 and IPv4 addresses.

The bind() Socket API

Applications use bind()() to specify the local address with which an SCTP endpoint must associate.

These addresses, associated with a socket, are eligible transport addresses for the endpoint to send and receive data. The endpoint also presents these addresses to its peers during the association initialization process. To accept new associations on the socket, the endpoint must call listen()(), after calling bind()(). For information on listen()(), see “The listen() Socket API”.

Following is the syntax for the bind()() API:

ret = bind(int sd, struct sockaddr *addr, socklen_t addrlen);

where:

sd

Represents the socket descriptor returned by the socket()() call.

addr

Represents the address structure (struct sockaddr_in or struct sockaddr_in6).

addrlen

Represents the size of the address structure.

If sd is an IPv4 socket, the address passed must be an IPv4 address. If sd is an IPv6 socket, the address passed can either be an IPv4 or an IPv6 address.

Applications cannot call bind()() multiple times to associate multiple addresses to an endpoint. After the first call to bind()(), all the subsequent calls will return an error.

If addr is specified as a wildcard (INADDR_ANY for an IPv4 address, or IN6ADDR_ANY_INIT or in6addr_any for an IPv6 address), the operating system associates the endpoint with an optimal address set of the available interfaces. If bind()() is not called before a sendmsg()() call that initiates a new association, the endpoint picks a transient port and chooses an address set that is equivalent to binding with a wildcard address. One of the addresses in the address set serves as the primary address for the association. Thus, when an application calls bind()() with the INADDR_ANY or the IN6ADDR_ANY_INIT wildcard address, the multihoming feature is enabled in SCTP.

The completion of the bind()() process alone does not prepare the SCTP endpoint to accept inbound SCTP association requests. When a listen()() system call is performed on the socket, the SCTP endpoint promptly rejects an inbound INIT request using an ABORT flag.

The listen() Socket API

Applications use listen()() to prepare the SCTP endpoint for accepting inbound associations.

Following is the syntax for the listen()() socket API:

int listen(int sd, int backlog);

where:

sd

Represents the socket descriptor of the SCTP endpoint.

backlog

Represents the maximum number of outstanding associations allowed in the accept queue of the socket. These associations have completed the four-way initiation handshake and are in the ESTABLISHED state. A backlog of 0 (zero) indicates that the caller no longer wants to receive new associations.

The accept() Socket API

Applications use the accept()() call to remove an established SCTP association from the accept queue. The accept()() API returns a new socket descriptor, to represent the newly formed association.

Following is the syntax for the accept()() socket API:

new_sd = accept(int sd, struct sockaddr *addr, socklen_t *addrlen);

where:

new_sd

Represents the socket descriptor for the newly formed association.

sd

Represents the listening socket descriptor.

addr

Contains the primary address of the peer endpoints.

addrlen

Specifies the size of addr.

The connect() Socket API

Applications use connect()() to initiate an association with a peer.

Following is the syntax for the connect()() socket API:

int connect(int sd, const struct sockaddr *addr, socklen_t addrlen);

where:

sd

Represents the socket descriptor of the endpoint.

addr

Represents the address of the peer.

addrlen

Represents the size of the address.

By default, the newly created association has only one outbound stream. Applications must use the SCTP_INITMSG option before connecting to the server, to change the number of outbound streams. The SCTP_INITMSG option enables you to set a socket option and get a socket option, using the setsockopt()() and getsockopt()() APIs.

If SCTP does not call the bind()() API before calling connect()() , the application picks a transient port and chooses an address set that is equivalent to binding with INADDR_ANY and IN6ADDR_ANY for IPv4 and IPv6 sockets, respectively. One of these addresses serves as the primary address for the association. When an application calls bind()() with the INADDR_ANY or the IN6ADDR_ANY_INIT wildcard address, the multihoming feature is enabled in SCTP.

The close() Socket API

Applications use close()() to gracefully close down an association.

Following is the syntax for the close()() socket API:

int close(int sd);

where:

sd

Represents the socket descriptor of the association to be closed.

After an application calls close()() on a socket descriptor, no further socket operations succeed on that descriptor.

The shutdown() Socket API

Applications use the shutdown()() socket API to disable send or receive operations at an endpoint. The effect of the shutdown()() call is different in SCTP and TCP. In TCP, a connection is in half-closed state even after an application calls shutdown()(). In the half-close state, an application at the sending endpoint continues to send data even if an application at the receiving endpoint has stopped receiving data. In SCTP, shutdown()() completely disables applications at both the endpoints from sending or receiving data.

NOTE: Applications can use the SCTP streams feature to achieve the half closed state in SCTP.

Following is the syntax for the shutdown()() socket call:

int shutdown(int sd, int how);
sd

Specifies the socket descriptor of the association that needs to be closed.

how

Specifies the type of shutdown. The values are as follows:

SHUT_RD

Disables further receive operations

SHUT_WR

Disables further send operations and initiates the SCTP shutdown sequence

SHUT_RDWR

Disables further send and receive operations, and initiates the SCTP shutdown sequence

In SCTP, SHUT_WR initiates an immediate and full protocol shutdown. In TCP, SHUT_WR causes TCP to enter a half-closed state. The SHUT_RD value behaves in the same way for SCTP and TCP. SCTP_WR closes the SCTP association while leaving the socket descriptor open, so that the receiving endpoint can receive data that SCTP was unable to deliver.

The sendmsg() and recvmsg() Socket APIs

Applications use the sendmsg()() and recvmsg()() socket APIs to transmit data to and receive data from its peer.

Following is the syntax for the sendmsg()() and recvmsg()() socket APIs:

ssize_t sendmsg(int sd, const struct msghdr *message, int flags);
ssize_t recvmsg(int sd, struct msghdr *message, int flags);

where:

sd

Represents the socket descriptor of the endpoint.

message

Specifies the pointer to the msghdr structure that contains a single user message and the ancillary data. Following is the structure for the msghdr structure:

struct msghdr {
  void        *msg_name; 
  socklen_t   msg_namelen;
  struct iovec  *msg_iov;
  size_t     msg_iovlen; 
  void      *msg_control;
  socklen_t  msg_controllen;
  int        msg_flags;
 };

where:

msg_name

Specifies the pointer to the socket address structure.

msg_namelen

Specifies the size of the socket address structure.

msg_iov

Includes an array of message buffers.

msg_iovlen

Specifies the number of elements in the msg_iov structure.

msg_control

Specifies the ancillary data.

msg_controllen

Specifies the length of the ancillary data buffer.

msg_flags

Specifies the flags on the received message.

For more information on the msghdr, see RFC 2292 (Advanced Sockets API for IPv6).

flags

Contains flags that affect the messages being sent or received

NOTE: A sendmsg()() API does not fail if it contains an invalid SCTP stream identifier but an error is returned on all subsequent calls on the file descriptor.

The getpeername() Socket API

Applications use the getpeername()() socket API to retrieve the primary socket address of the peer.

Following is the syntax for the getpeername()() socket API:

int getpeername(int sd, struct sockaddr *address, socklen_t *len);

where:

sd

Specifies the socket descriptor to be queried.

address

Contains the primary peer address. If the socket is an IPv4 socket, the address will be an IPv4 address. If the socket is an IPv6 socket, the address will be either an IPv6 or an IPv4 address.

len

Specifies the length of the address.

If the actual length of the address is greater than the length of the supplied sockaddr structure, SCTP truncates the stored address.

NOTE: The getpeername()() socket API is available only for TCP compatibility. It must not be used for the multihoming feature in SCTP, because this socket API does not work with one-to-many style sockets.

One-to-Many Socket APIs

The one-to-many style APIs are designed to enable applications to control many associations from a single endpoint, using a single file descriptor. Similar to the APIs in UDP, one-to-many style APIs in SCTP enable a single socket file descriptor to connect to multiple remote endpoints. A one-to-many style socket can send and receive data without connecting to an endpoint. Unlike UDP, however, SCTP always has a valid association with the specified endpoints, because SCTP is a connection-oriented protocol.

Basic One-to-Many Call Flow Sequence

A server in the one-to-many style uses the following socket call sequence to prepare an endpoint for servicing requests:

  1. socket()()

  2. bind()() or sctp_bindx()()

  3. sctp_getladdrs()()

  4. sctp_freeladdrs()()

  5. listen()()

  6. sctp_getpaddrs()()

  7. sctp_setpaddrs()()

  8. recvmsg()() or sctp_recvmsg()()

  9. sendmsg()() or sctp_sendmsg()()

  10. sctp_peeloff()()

  11. close()()

A client in the one-to-many style API uses the following call sequence to set up an association with a server, and to request services from that server:

  1. socket()()

  2. sendmsg()() or sctp_sendmsg()()

  3. recvmsg()() or sctp_recvmsg()()

  4. close()()

By default, all the associations connected to an endpoint are represented with a single socket. Each association is assigned an association ID (of type uint32_t sctp_assoc_t), so that an application can use it to differentiate between different associations. Applications can also use the sendto()() call to set up an association. However, an application cannot use the sendto()() call to send data to an established association, because the association ID cannot be specified in the sendto()() call.

When an association ID is assigned to an SCTP association, SCTP must not reuse the ID until the application explicitly terminates the association. The resources belonging to that association are not freed until the association terminates. This is similar to the close()() call on a normal socket. The only difference between a normal socket and a one-to-many socket is the availability of the SCTP_AUTOCLOSE option in the one-to-many socket. When the SCTP_AUTOCLOSE option is set in a one-to-many socket, an application can reuse the association ID assigned to the association once the association terminates automatically. Applications that use this option must ensure that they do not send data to an incorrect peer endpoint, because the association ID is being reused.

A server or client can branch off an existing one-to-many association into a separate socket. When an association is branched off to a separate socket, the branched off socket is completely separated from the original socket. All subsequent control and data operations on that association must be done through the new socket. For example, the close()() operation on the original socket does not terminate associations that have been branched off to a different socket.

For more information on the one-to-many style socket APIs, see the subsequent subsections and “SCTP-Specific Socket APIs”.

The socket()() Socket API

The socket()() socket API is used to create a socket descriptor that represents an SCTP endpoint.

Following is the syntax for the socket()() socket API:

sd = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);

or

sd = socket(PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);

where:

SOCK_SEQPACKET

Indicates the creation of a one-to-one or one-to-many style socket.

IPProto_SCTP

Specifies the type of the protocol.

PF_INET

Specifies the IPv4 domain.

PF_INET6

Specifies the IPv6 domain.

The first syntax of socket()() creates an endpoint that can use only IPv4 addresses, while the second syntax creates an endpoint that can use both IPv6 and IPv4 addresses.

The bind() Socket API

Applications use bind()() to specify the local address to which an SCTP endpoint must associate.

An SCTP endpoint can be associated with multiple addresses. The sctp_bindx()() API enables applications to associate with multiple addresses. For information on sctp_bindx()(), see “The sctp_bindx() SCTP Socket API”. These addresses, associated with a socket, are eligible transport addresses for the endpoint to send and receive data. The endpoint also presents these addresses to its peers during the association initialization process. To accept new associations on the socket, applications must call listen()(), after calling bind()(). For information on listen()(), see “The listen() Socket API”.

Following is the syntax for the bind()() socket API:

ret = bind(int sd, struct sockaddr *addr, socklen_t addrlen);

where:

sd

Represents the socket descriptor returned by the socket()() call.

addr

Represents the address structure (struct sockaddr_in or struct sockaddr_in6).

addrlen

Represents the size of the address structure.

If sd is an IPv4 socket, the address passed must be an IPv4 address. If sd is an IPv6 socket, the address passed can be either an IPv4 or an IPv6 address.

Applications cannot call bind()() multiple times to associate multiple addresses to an endpoint. After the first call to bind()(), all the subsequent calls will return an error.

If addr is specified as a wildcard (INADDR_ANY for an IPv4 address, or IN6ADDR_ANY_INIT or in6addr_any for an IPv6 address), the operating system associates the endpoint with an optimal address set of the available interfaces.

If a bind()() call is not called before a sendmsg()() call that initiates a new association, the endpoint picks a transient port and chooses an address set that is equivalent to binding with a wildcard address. One of the addresses in the address set serves as the primary address for the association. This automatically enables the multi-homing feature of SCTP.

The listen() Socket API

An application uses listen()() to indicate that a socket is ready to accept new associations.

Following is the syntax for the listen()() socket API:

int listen(int sd, int backlog);

where:

sd

Specifies the socket descriptor of the endpoint.

backlog

Defines the number of connections in the listen queue.

By default, one-to-many style sockets do not accept new associations. If applications that use one-to-many style socket APIs call the accept()() API to accept new associations, SCTP returns the EOPNOTSUPP error to the application. In the one-to-many style socket APIs, new associations are accepted automatically and notifications of the new associations are delivered using the recvmsg()() API with the SCTP_ASSOC_CHANGE event (if these notifications are enabled). A client in a one-to-many association does not call listen()(). Therefore, clients can be assured that the only associations on the socket are the associations that are actively initiated. On the contrary, a server or a peer-to-peer socket in a one-to-many connection always accepts new associations. Therefore, an application running on a server using a one-to-many style API must be prepared to handle new associations from unwanted peers.

The SCTP_ASSOC_CHANGE event provides the association ID for a new association. If applications want to use the association ID as input for other socket calls, they must ensure that the SCTP_ASSOC_CHANGE event is enabled (it is enabled by default).

The sendmsg() and recvmsg() Socket APIs

An application uses sendmsg()() and recvmsg()() calls to transmit data to and receive data from its peer.

ssize_t sendmsg(int sd, const struct msghdr *message, int flags);
ssize_t recvmsg(int sd, struct msghdr *message, int flags);

where:

sd

Specifies the socket descriptor.

message

Specifies the pointer to the msghdr structure, which contains a single user message and the ancillary data.

flags

Contains flags that affect messages that are being sent and received.

The close() Socket API

Applications use close()() to gracefully shutdown all the associations represented by a one-to-many style socket.

Following is the syntax for the close()() socket API:

close(int sd);

where:

sd

Specifies the socket descriptor of the associations to be closed.

To gracefully shutdown a specific association that is represented by the one-to-many style socket, an application must use the sendmsg()() call and include the MSG_EOF flag. A user can optionally terminate an association non-gracefully by sending the MSG_ABORT flag, and possibly by passing a user specified abort code in the data field. Both the flags, MSG_EOF and MSG_ABORT, are passed with ancillary data in the sendmsg()() call.

If sd in the close()() call is a branched-off socket that represents only one association, the shutdown is performed only on that association.

The connect() Socket API

An application can use the connect()() call in the one-to-many style to initiate an association without sending data.

Following is the syntax for the connect()() socket API:

connect(int sd, const struct sockaddr *nam, socklen_t len);

where:

sd

Specifies the socket descriptor for a new association.

len

Specifies the size of the address.

Multiple connect()() calls can be made on the same socket to create multiple associations. In UDP, a connect()() call cannot make multiple associations on the same socket.

Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© 2007–2008 Hewlett-Packard Development Company, L.P.