connect —
initiate a connection on a socket
Standard C Library (libc, -lc)
#include
<sys/types.h>
#include
<sys/socket.h>
int
connect(
int s,
const struct sockaddr *name,
socklen_t namelen);
The parameter
s is a socket. If it is of type
SOCK_DGRAM
,
connect() specifies the peer with which the
socket is to be associated. This address is the address to which datagrams are
to be sent if a receiver is not explicitly designated. This address is the
only address from which datagrams are to be received. If the socket
s is of type
SOCK_STREAM
,
connect() attempts to make a connection to
another socket. The other socket is specified by
name.
name
is an address in the communication space of the socket. Each communication
space interprets the
name parameter in its
own way. If
s is not bound, then
s will be bound to an address selected by the
underlying transport provider. Generally, stream sockets can successfully
connect() only once. Datagram sockets can use
connect() multiple times to change their
association. Datagram sockets can dissolve the association by connecting to a
null address.
When a socket is created, it is by default a blocking socket. A socket may be
configured to be non-blocking either at socket creation time or through the
use of
fcntl(2). When a socket is set to be
non-blocking, a call to
connect() initiates an
asynchronous connection. If the connection cannot be completed without
blocking, such as when making a TCP connection to a remote server, then the
connection attempt is made in the background and
connect() returns -1 and
errno is set to
EINPROGRESS
.
Applications can obtain the state of this connection attempt by polling the
socket's file descriptor for
POLLOUT
. The
event ports facility is the preferred means of polling on the file descriptor,
see
port_create(3C) and
port_get(3C) for more information on event ports;
however, applications may also use traditional portable routines like
poll(2) and
select(3C).
When an asynchronous connection has completed, the application must call
getsockopt(3C) using the macro
SOL_SOCKET
as the
level argument and the macro
SO_ERROR
as the value of the
option argument. If the value of the
SO_ERROR
socket option is zero, then the
connect was successfully established. Otherwise, the connection could not be
established and the value is the corresponding error code that would be
commonly found in
errno.
Even when a socket is in non-blocking mode, a call to
connect() may fail synchronously. If any error
other than
EINPROGRESS
or
EINTR
occurs, then there is no need for the
application to poll for asynchronous completion. Similarly, if a call to
connect() returns successfully, then the socket
connection will be established and there is no need to poll for completion.
If the connection or binding succeeds, 0 is returned. Otherwise, -1 is returned
and sets
errno to indicate the error.
-
-
- Example 1
Performing an asynchronous connection
- The following sample C program shows how to create and
connect to a remote host using TCP.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <errno.h>
#include <port.h>
#include <unistd.h>
#include <assert.h>
int
main(int argc, char *argv[])
{
char *eptr;
long port;
int sock, ret, eport;
struct sockaddr_in6 sin6;
if (argc != 3) {
fprintf(stderr, "connect: <IP> <port>\n");
return (1);
}
bzero(&sin6, sizeof (struct sockaddr_in6));
sin6.sin6_family = AF_INET6;
/*
* Try to parse as an IPv6 address and then try v4.
*/
ret = inet_pton(AF_INET6, argv[1], &sin6.sin6_addr);
if (ret == -1) {
perror("inet_pton");
return (1);
} else if (ret == 0) {
struct in_addr v4;
ret = inet_pton(AF_INET, argv[1], &v4);
if (ret == -1) {
perror("inet_pton");
return (1);
} else if (ret == 0) {
fprintf(stderr, "connect: %s is not a valid "
"IPv4 or IPv6 address\n", argv[1]);
return (1);
}
/* N.B. Not a portable macro */
IN6_INADDR_TO_V4MAPPED(&v4, &sin6.sin6_addr);
}
errno = 0;
port = strtol(argv[2], &eptr, 10);
if (errno != 0 || *eptr != '\0') {
fprintf(stderr, "failed to parse port %s\n", argv[2]);
return (1);
}
if (port <= 0 || port > UINT16_MAX) {
fprintf(stderr, "invalid port: %ld\n", port);
return (1);
}
sin6.sin6_port = htons(port);
sock = socket(AF_INET6, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (sock < 0) {
perror("socket");
return (1);
}
eport = port_create();
if (eport < 0) {
perror("port_create");
(void) close(sock);
return (1);
}
ret = connect(sock, (struct sockaddr *)&sin6,
sizeof (struct sockaddr_in6));
if (ret != 0 && errno != EINPROGRESS && errno != EINTR) {
perror("connect");
(void) close(sock);
(void) close(eport);
return (1);
}
if (ret != 0) {
port_event_t pe;
int err;
socklen_t sz = sizeof (err);
if (port_associate(eport, PORT_SOURCE_FD, sock, POLLOUT,
NULL) != 0) {
perror("port_associate");
(void) close(sock);
(void) close(eport);
return (1);
}
if (port_get(eport, &pe, NULL) != 0) {
perror("port_get");
(void) close(sock);
(void) close(eport);
return (1);
}
assert(pe.portev_source == PORT_SOURCE_FD);
assert(pe.portev_object == (uintptr_t)sock);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &sz) != 0) {
perror("getsockopt");
(void) close(sock);
(void) close(eport);
return (1);
}
if (err != 0) {
/* Asynch connect failed */
fprintf(stderr, "asnchronous connect: %s\n",
strerror(err));
(void) close(sock);
(void) close(eport);
return (1);
}
}
/* Read and write to the socket and then clean up */
return (0);
}
The call fails if:
-
-
- [
EACCES
]
- Search permission is denied for a component of the path
prefix of the pathname in name.
-
-
- [
EADDRINUSE
]
- The address is already in use.
-
-
- [
EADDRNOTAVAIL
]
- The specified address is not available on the remote
machine.
-
-
- [
EAFNOSUPPORT
]
- Addresses in the specified address family cannot be used
with this socket.
-
-
- [
EALREADY
]
- The socket is non-blocking, and a previous connection
attempt has not yet been completed.
-
-
- [
EBADF
]
- s is not a valid
descriptor.
-
-
- [
ECONNREFUSED
]
- The attempt to connect was forcefully rejected. The calling
program should close(2) the socket
descriptor, and issue another socket(3C) call
to obtain a new descriptor before attempting another
connect() call.
-
-
- [
EINPROGRESS
]
- The socket is non-blocking, and the connection cannot be
completed immediately. See the section on
Non-blocking
Sockets for more information.
-
-
- [
EINTR
]
- The connection attempt was interrupted before any data
arrived by the delivery of a signal. The connection, however, will be
established asynchronously.
-
-
- [
EINVAL
]
- namelen is not the size of
a valid address for the specified address family.
-
-
- [
EIO
]
- An I/O error occurred while reading from or writing to the
file system.
-
-
- [
EISCONN
]
- The socket is already connected.
-
-
- [
ELOOP
]
- Too many symbolic links were encountered in translating the
pathname in name.
-
-
- [
ENETUNREACH
]
- The network is not reachable from this host.
-
-
- [
EHOSTUNREACH
]
- The remote host is not reachable from this host.
-
-
- [
ENOENT
]
- A component of the path prefix of the pathname in
name does not exist.
The socket referred to by the pathname in
name does not exist.
-
-
- [
ENOSR
]
- There were insufficient STREAMS resources available to
complete the operation.
-
-
- [
ENXIO
]
- The server exited before the connection was complete.
-
-
- [
ETIMEDOUT
]
- Connection establishment timed out without establishing a
connection.
-
-
- [
EWOULDBLOCK
]
- The socket is marked as non-blocking, and the requested
operation would block.
The following errors are specific to connecting names in the UNIX domain. These
errors might not apply in future versions of the UNIX IPC domain.
-
-
- [
ENOTDIR
]
- A component of the path prefix of the pathname in
name is not a directory.
-
-
- [
ENOTSOCK
]
- s is not a socket.
-
-
- [
EPROTOTYPE
]
- The file that is referred to by
name is a socket of a type other than
type s. For example,
s is a
SOCK_DGRAM
socket, while
name refers to a
SOCK_STREAM
socket.
Safe
close(2),
accept(3C),
getsockname(3C),
select(3C),
sockaddr(3C),
socket(3C),
socket.h(3HEAD),
attributes(5)