tcp协议系列文章(8):connect:在socket上进行连接初始化

时间:2022-01-25 22:00:34



NAME

       connect - initiate a connection on a socket


SYNOPSIS

       #include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

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


DESCRIPTION

       The  connect() system call connects the socket referred to by the file descriptor sockfd to the address specified by addr.  The addrlen argument specifies the size of addr.  The format of the address in addr is determined by the address space of the socket sockfd; see socket(2) for further details.
  connect()系统调用连接sockfd指定的socket到addr指定的地址上。参数addrlen是addr的长度。addr的结构由sockfd的地址空间决定。查看socket(2)获取更多细节。

       If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.  If the socket is of type SOCK_STREAM or SOCK_SEQPACKET, this call attempts to make a connection to the socket that is bound to the address specified by addr.
  如果sockfd是SOCK_DGRAM类型,那么addr是数据报默认的发送目的地址,也是接收的数据报源的唯一地址。如果sockfd是SOCK_STREAM或SOCK_SEQPACKET类型,该调用尝试与addr绑定的socket建立连接。


       Generally,  connection-based  protocol sockets may successfully connect() only once; connectionless protocol sockets may use connect() multiple times to change their association.  Connectionless sockets may dissolve the association by connecting to an address with the sa_family member of sockaddr set to AF_UNSPEC (supported on Linux since kernel 2.2).
  通常,基于连接的协议socket只能成功connect()一次。无连接的协议socket能多次使用connect()改变它们的关联性。当一个地址的sockaddr的sa_family成员设置为AF_UNSPEC(自linux2.2内核开始支持),无连接socket连接该地址时,会分解关联性。

RETURN VALUE

       If the connection or binding succeeds, zero is returned.  On error, -1 is returned, and errno is set appropriately.

ERRORS

The following are general socket errors only.  There may be other domain-specific error codes.

下面只是一些socket错误。还可能有域相关的错误码未列其中。


       EACCES For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket file, or search permission is denied for one of the directories in  the  path prefix.  (See also path_resolution(7).)


       EACCES, EPERM
              The user tried to connect to a broadcast address without having the socket broadcast flag enabled or the connection request failed because of a local firewall rule.
              用户尝试连接一个广播地址但却没有设置socket的广播标识,或者因为本地防火墙规则而导致连接请求失败。


       EADDRINUSE
              Local address is already in use.


       EAFNOSUPPORT
              The passed address didn't have the correct address family in its sa_family field.
              不支持的协议簇域sa_family。


       EADDRNOTAVAIL
              Non-existent interface was requested or the requested address was not local.
              请求的地址不存在或不在本局域网内。


       EALREADY
              The socket is nonblocking and a previous connection attempt has not yet been completed.
              socket是非阻塞的,但前一个连接请求尚未完毕。


       EBADF  The file descriptor is not a valid index in the descriptor table.
              sockfd参数在描述符表中无效。


       ECONNREFUSED
              No-one listening on the remote address.
              远程地址上没有哪个sockfd在监听。


       EFAULT The socket structure address is outside the user's address space.

       EINPROGRESS
              The  socket is nonblocking and the connection cannot be completed immediately.  It is possible to select(2) or poll(2) for completion by selecting the socket for writing.  After select(2) indicates writability, use getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR  is  zero)  or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure).
              socket是非阻塞的,连接可能不会立刻完毕。可以用select(2)或poll(2),通过检查可写性,来检查是否完毕。在select(2)指示可写后,使用getsockopt(2)在SOL_SOCKET层读取SO_ERROR选项,以此来决定connect()是成功还是失败。成功时SO_ERROR为0。失败时SO_ERROR是这里列出的这么多错误码中的一个。
              笔者注:从这段话中可以推测出“当失败时,sockfd具备可写性。”吗?笔者一开始认为答案是肯定的。但是在回顾select(2)的man手册后,却并不这么认为。select指出是“事件改变”就会返回,而不是可写性发生才返回。详细可查看笔者的另一篇博文:
              tcp协议系列文章(5):select:同步I/O复用


       EINTR  The system call was interrupted by a signal that was caught; see signal(7).


       EISCONN
              The socket is already connected.


       ENETUNREACH
              Network is unreachable.


       ENOTSOCK
              The file descriptor is not associated with a socket.


       ETIMEDOUT
              Timeout while attempting connection.  The server may be too busy to accept new connections.  Note that for IP sockets the timeout may be very long when syncookies are enabled on the server.
              尝试连接却超时。服务端可能因为太忙碌而无法再接受新的连接。注意,对IP socket,当syncookies到达服务端时,超时时间可能非常长。

CONFORMING TO

       SVr4, 4.4BSD, (the connect() function first appeared in 4.2BSD), POSIX.1-2001.

NOTES

       POSIX.1-2001 does not require the inclusion of <sys/types.h>, and this header file is not required on Linux.  However, some historical (BSD) implementations required this header  file, and portable applications are probably wise to include it.

       The  third  argument of connect() is in reality an int (and this is what 4.x BSD and libc4 and libc5 have).  Some POSIX confusion resulted in the present socklen_t, also used by glibc.
       See also accept(2).

EXAMPLE

       An example of the use of connect() is shown in getaddrinfo(3).

SEE ALSO

       accept(2), bind(2), getsockname(2), listen(2), socket(2), path_resolution(7)


COLOPHON

       This  page  is  part  of  release  3.53  of  the  Linux  man-pages  project.   A  description  of  the  project,   and   information   about   reporting   bugs,   can   be   found   at
       http://www.kernel.org/doc/man-pages/.