16.4. Connection EstablishmentIf we're dealing with a connection-oriented network service (SOCK_STREAM or SOCK_SEQPACKET), then before we can exchange data, we need to create a connection between the socket of the process requesting the service (the client) and the process providing the service (the server). We use the connect function to create a connection.[View full width]#include <sys/socket.h> int connect(int sockfd , const struct sockaddr ![]() |
Returns: 0 if OK, 1 on error |
Example
Figure 16.9 shows one way to handle transient connect errors. This is likely with a server that is running on a heavily loaded system.This function shows what is known as an exponential backoff algorithm. If the call to connect fails, the process goes to sleep for a short time and then tries again, increasing the delay each time through the loop, up to a maximum delay of about 2 minutes.
Figure 16.9. Connect with retry
#include "apue.h"
#include <sys/socket.h>
#define MAXSLEEP 128
int
connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen)
{
int nsec;
/*
* Try to connect with exponential backoff.
*/
for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
if (connect(sockfd, addr, alen) == 0) {
/*
* Connection accepted.
*/
return(0);
}
/*
* Delay before trying again.
*/
if (nsec <= MAXSLEEP/2)
sleep(nsec);
}
return(-1);
}
Section 16.8, connect will return 1 with errno set to the special error code EINPROGRESS if the connection can't be established immediately. The application can use either poll or select to determine when the file descriptor is writable. At this point, the connection is complete.The connect function can also be used with a connectionless network service (SOCK_DGRAM). This might seem like a contradiction, but it is an optimization instead. If we call connect with a SOCK_DGRAM socket, the destination address of all messages we send is set to the address we specified in the connect call, relieving us from having to provide the address every time we transmit a message. In addition, we will receive datagrams only from the address we've specified.A server announces that it is willing to accept connect requests by calling the listen function.
#include <sys/socket.h> int listen(int sockfd , int backlog ); |
Returns: 0 if OK, 1 on error |
#include <sys/socket.h> int accept(int sockfd , struct sockaddr *restrict addr , socklen_t *restrict len ); |
Returns: file (socket) descriptor if OK, 1 on error |
Example
Figure 16.20 shows a version of this function that bypasses these rules, solving the major drawback with this version.
Figure 16.10. Initialize a socket endpoint for use by a server
#include "apue.h"
#include <errno.h>
#include <sys/socket.h>
int
initserver(int type, const struct sockaddr *addr, socklen_t alen,
int qlen)
{
int fd;
int err = 0;
if ((fd = socket(addr->sa_family, type, 0)) < 0)
return(-1);
if (bind(fd, addr, alen) < 0) {
err = errno;
goto errout;
}
if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
if (listen(fd, qlen) < 0) {
err = errno;
goto errout;
}
}
return(fd);
errout:
close(fd);
errno = err;
return(-1);
}