socket api 存在一批核心接口,而这一批核心接口就是几个看似简单的函数,尽管实际上这些函数没有一个是简单。connect 函数就是这些核心接口中的一个函数,它完成主动链接的过程。 linux
connect 函数的功能对于 TCP 来讲就是完成面向链接的协议的链接过程,它的函数原型:
linux下 windows
#include<sys/socket.h>
#include<sys/types.h>
int connect(int sockfd, const struct sockaddr* server_addr, socklen_t addrlen)
windows下
int connect(
SOCKET s, // 没绑定套接口描述字
const struct sockaddr FAR *name, // 目标地址指针,目标地址中必须包含IP和端口信息。
int namelen // name的长度
);
面向链接的协议,在创建链接的时候总会有一方先发送数据(SYN),那么谁调用了 connect 谁就是先发送数据的一方。如此理解 connect 三个参数就容易了。我必需指定数据发送的目的地址,同时也必需指定数据从哪里发送,这正好是 connect 的前两个参数,而第三个参数是为第二个参数服务的。
参数
sockfd
指定数据发送的套接字,解决从哪里发送的问题。内核须要维护大量 I/O 通道,因此用户必需经过这个参数告诉内核从哪一个 I/O 通道(此处就是从哪一个 socket 接口)中发送数据。
参数
server_addr
指定数据发送的目的地,也就是服务器端的地址。这里服务器是针对 connect 说的,由于 connect 是主动链接的一方调用的,因此相应的要存在一个被链接的一方,被动链接的一方须要调用 listen 以接受 connect 的链接请求,如此被动链接的一方就是服务器了。
参数
addrlen
指定 server_addr 结构体的长度。咱们知道系统中存在大量的地址结构,但 socket 接口只是经过一个统一的结构来指定参数类型,因此须要指定一个长度,以使内核在进行参数复制的时候有个界限。
返回值:没有错误发生,返回0;不然返回 SOCKET_ERROR(-1) 。 后端
==================== api
与全部的 socket 网络接口同样,connect 总会在某个时候可能失败,此时它会返回 -1 ,相应的 errno 会被设置,用户可能经过这个值肯定是哪一个错误。常见的错误有对方主机不可达或者超时错误,也能够是对方主机没有相应的进程在对应端口等待。 服务器
connect 函数可用于
面向链接套接字,
也可用于
无链接套接字
。
无链接套接字
:对于无链接的套接字 (SOCK_DGRAM) ,该套接字与目标地址之间创建默认的对应关系,且在本地保存了对端的地址,这样后续的读写操做能够默认以链接的对端为操做对象,网络数据交互发生时能够直接使用 send ,而不是用 sendto 来向该地址发送数据;内核会丢弃全部发送给该套接字的源地址不是 connect 地址的报文。再次调用 connect 函数,若此时 name 和 namelen 两个参数均为空指针,就会将该套接字恢复为未链接状态,再调用 send 函数,系统会提示 WSAENOTCONN 错误码。
面向链接套接字
:面向链接的套接字 (SOCK_STREAM) ,函数 connect 会引发调用端主动进行 TCP 的三次握手过程。结果一般是成功链接、WSAETIMEDOUT (屡次发送SYN报文,始终未收到回复)、WSAECONNREFUSED (目标主机返回 RST) 等。
当对端机器 crash 或者网络链接被断开(好比路由器不工做,网线断开等),此时发送数据给对端而后,读取本端 socket 会返回 ETIMEDOUT 或者 EHOSTUNREACH 或者 ENETUNREACH (后两个是中间路由器判断服务器主机不可达的状况)。
当对端机器 crash 以后又从新启动,而后客户端再向原来的链接发送数据,由于服务器端已经没有原来的链接信息,此时服务器端回送 RST 给客户端,此时客户端读本地端口返回 ECONNRESET 错误。
当服务器所在的进程正常或者异常关闭时,会对全部打开的文件描述符进行 close ,所以对于链接的 socket 描述符则会向对端发送 FIN 分节进行正常关闭流程。对端在收到 FIN 以后端口变得可读,此时读取端口会返回 0 表示到了文件结尾(对端不会再发送数据)。
当一端收到 RST 致使读取 socket 返回 ECONNRESET ,此时若是再次调用 write 发送数据给对端则触发 SIGPIPE 信号,信号默认终止进程,若是忽略此信号或者从 SIGPIPE 的信号处理程序返回则 write 出错返回 EPIPE 。
=================================
=====
1) Broken PIPE 的字面意思是“管道破裂”。Broken PIPE 产生的缘由是该管道的读端被关闭。
2) Broken PIPE 常常发生在 Client 端经过 Socket 发送信息到 Server 端后,就关闭当前 Socket , 以后 Server 端回复信息给 Client 端时。
3) 发生 Broken PIPE 错误时,调用写的进程会收到 SIGPIPE 信号,默认动做是致使当前进程终止。
4) Broken PIPE 最直接的意思是:写入端出现的时候,PIPE 的另外一端却休息或退出了,所以形成没有及时取走管道中的数据,从而系统异常退出。
Client 端经过 PIPE 发送信息到 Server 端后,就关闭 Client 端 Socket , 这时 Server 端返回信息给 Client 端时就会产生 Broken PIPE 信号。
====================================== 网络
能够看出,只有当本地端口主动发送消息给对端时,才能检测出链接异常中断的状况,搭配 select 进行多路分离的时候,socket 收到 RST 或者 FIN 时候,select 返回可读(心跳消息就是用于检测链接的状态)。也可使用 socket 的 KEEPLIVE 选项,依赖 socket 自己侦测 socket 链接异常中断的状况。
错误信息:
EACCES, EPERM:用户试图在套接字广播标志没有设置的状况下链接广播地址或因为防火墙策略致使链接失败。
EADDRINUSE:本地地址处于使用状态。
EAFNOSUPPORT:参数 serv_add 中的地址非法。
EAGAIN:没有足够空闲的本地端口。
EALREADY:套接字为非阻塞套接字,而且原来的链接请求还未完成。
EBADF:非法的文件描述符。
ECONNREFUSED:远程地址并无处于监听状态。
EFAULT:指向套接字结构体的地址非法。
EINPROGRESS:套接字为非阻塞套接字,且链接请求没有当即完成。
EINTR:系统调用的执行因为捕获中断而停止。
EISCONN:已经链接到该套接字。
ENETUNREACH:网络不可到达。
ENOTSOCK:文件描述符不与套接字相关。
ETIMEDOUT:链接超时。 socket