网络编程socket之connect函数
网络编程socket api存在一批核心接口,而这一批核心接口就是几个看似简单的函数,尽管实际上这些函数没有一个是简单。connect函数就是这些核心接口的一个函数,它完成主动连接的过程。
connect函数的功能是完成一个有连接协议的连接过程,对于TCP来说就是那个三路握手过程,它的函数原型:
#include<sys/socket.h>#include<sys/types.h>int connect(int sockfd, const struct sockaddr* server_addr, socklen_t addrlen)
返回:0──成功, -1──失败。换一种写法:int connect(
SOCKET s, // 没绑定套接口描述字
const struct sockaddr FAR *name, // 目标地址指针,目标地址中必须包含IP和端口信息。
int namelen // name的长度
);
为了理解connect函数,我们需要对connect函数的功能进行介绍。connect函数的功能可以用一句话来概括,就是完成面向连接的协议的连接过程,它是主要连接的。面向连接的协议,在建立连接的时候总会有一方先发送数据,那么谁调用了connect谁就是先发送数据的一方。如此理解connect三个参数是容易了,我必需指定数据发送的地址,同时也必需指定数据从哪里发送,这正好是connect的前两个参数,而第三个参数是为第二个参数服务的。
参数sockfd
指定数据发送的套接字,解决从哪里发送的问题。内核需要维护大量IO通道,所以用户必需通过这个参数告诉内核从哪个IO通道,此处就是从哪个socket接口中发送数据。sockfd是先前socket返回的值。
参数server_addr
指定数据发送的目的地,也就是服务器端的地址。这里服务器是针对connect说的,因为connect是主动连接的一方调用的,所以相应的要存在一个被连接的一方,被动连接的一方需要调用listen以接受connect的连接请求,如此被动连接的一方就是服务器了。
参数addrlen
指定server_addr结构体的长度。我们知道系统中存在大量的地址结构,但socket接口只是通过一个统一的结构来指定参数类型,所以需要指定一个长度,以使内核在进行参数复制的时候有个有个界限。
与所有的socket网络接口一样,connect总会在某个时候可能失败,此时它会返回-1,相应的errno会被设置,用户可能通过这个值确定是哪个错误。常见的错误有对方主机不可达或者超时错误,也可以是对方主机没有相应的进程在对应端口等待。
返回值:没有错误发生,返回0;否则返回SOCKET_ERROR。connect函数可用于面向连接套接字,也可用于无连接套接字。
无连接套接字:对于无连接的套接字(SOCK_DGRAM)
该套接字与目标地址之间建立默认的对应关系,网络数据交互发生。可以直接使用 send,而不是用sendto来向该地址发送数据;内核会丢弃所有发送给该套接字的源地址不是connect 地址的报文。再次调用connect函数:此时name和namelen两个参数均为空指针,就会将该套接字恢复为未连接状态,再调用send函数,系统会提示WSAENOTCONN错误码。
面向连接套接字:面向连接的套接字(SOCK_STREAM),函数connect会引起调用端主动进行TCP的三次握手过程。结果通常是成功连接、WSAETIMEDOUT(多次发送SYN报文,始终未收到回复)、WSAECONNREFUSED(目标主机返回TCP-RST)等。
说明:
connect函数将使用参数sockfd中的套接字连接到参数serv_addr中指定的服务器。参数addrlen为serv_addr指向的内存空间大小。
如果参数sockfd的类型为SOCK_DGRAM,serv_addr参数为数据报发往的地址,且将只接收该地址的数据报。如果sockfd的类型为SOCK_STREAM或SOCK_SEQPACKET,调用该函数将连接serv_addr中的服务器地址。
错误信息:
EACCES, EPERM:用户试图在套接字广播标志没有设置的情况下连接广播地址或由于防火墙策略导致连接失败。
EADDRINUSE:本地地址处于使用状态。
EAFNOSUPPORT:参数serv_add中的地址非合法地址。
EAGAIN:没有足够空闲的本地端口。
EALREADY:套接字为非阻塞套接字,并且原来的连接请求还未完成。
EBADF:非法的文件描述符。
ECONNREFUSED:远程地址并没有处于监听状态。
EFAULT:指向套接字结构体的地址非法。
EINPROGRESS:套接字为非阻塞套接字,且连接请求没有立即完成。
EINTR:系统调用的执行由于捕获中断而中止。
EISCONN:已经连接到该套接字。
ENETUNREACH:网络不可到达。
ENOTSOCK:文件描述符不与套接字相关。
ETIMEDOUT:连接超时。