网络编程0x02: connect函数及其errno
文章目录
1. connect函数
对于客户机而言,要与服务器进行通信,首先需要向服务器发出连接请求。
connect函数用于完成这项功能,connect函数签名如下:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
RETURN VALUE
If the connection or binding succeeds, zero is returned. On error, -1 is returned, and errno is set appropriately.
成功返回0,失败返回-1,并且将设置errno
说明:connect函数将使用参数sockfd中的套接字连接到参数serv_addr中指定的服务器。参数addrlen为serv_addr指向的内存空间大小。
如果参数sockfd的类型为SOCK_DGRAM,serv_addr参数为数据报发往的地址,且将只接收该地址的数据报。如果sockfd的类型为SOCK_STREAM或SOCK_SEQPACKET,调用该函数将连接serv_addr中的服务器地址。
错误信息:
整数 | 宏 | 描述 |
---|---|---|
13 | EACCES, EPERM | 用户试图在套接字广播标志没有设置的情况下连接广播地址或由于防火墙策略导致连接失败 |
98 | EADDRINUSE | 本地地址处于使用状态 |
97 | EAFNOSUPPORT | 参数serv_add中的地址非合法地址 |
11 | EAGAIN | 没有足够空闲的本地端口 |
114 | EALREADY | 套接字为非阻塞套接字,并且原来的连接请求还未完成 |
9 | EBADF | 非法的文件描述符 |
111 | ECONNREFUSED | 远程地址并没有处于监听状态 |
14 | EFAULT | 指向套接字结构体的地址非法 |
115 | EINPROGRESS | 套接字为非阻塞套接字,且连接请求没有立即完成 |
4 | EINTR | 系统调用的执行由于捕获中断而中止 |
106 | EISCONN | 已经连接到该套接字 |
101 | ENETUNREACH | 网络不可到达 |
88 | ENOTSOCK | 文件描述符不与套接字相关 |
110 | ETIMEDOUT | 连接超时 |
2. SOCKET中连接过程比较
connect是套接字连接操作,connect操作之后代表对应的套接字已连接,UDP协议在创建套接字之后,可以同多个服务器端建立通信,而TCP协议只能与一个服务器端建立通信,TCP不允许目的地址是广播或多播地址,UDP允许。当然UDP协议也可以像TCP协议一样,通过connect来指定对方的ip地址、端口。
UDP协议经过connect之后,在通过sendto来发送数据报时不需要指定目的地址、端口,如果指定了目的地址、端口,那么会返回错误。通过UDP协议可以给同一个套接字指定多次connect操作,而TCP协议不可以,TCP只能指定一次connect操作。UDP协议指定第二次connect操作之后会先断口第一次的连接,然后建立第二次的连接。
3. 客户端在建立同服务器端的连接过程
Step1:通过socket建立连接套接字;
Step2:通过bind来绑定本地地址、本地端口,当然绑定操作可以不用指定;
- 对于UDP协议:若未指定绑定操作,那么可以通过下面connect操作来由内核负责套接字的绑定操作,若
connect又未指定,那么绑定操作只好通过套接字的写操作(sendto、sendmsg)来指定目的地址、端口,这时套接字本地地址不会指定,为通配地址,而本地端口由内核指定,第一次sendto操作之后,插口的本地端口经过内核指定之后就不会更改。 - 对于TCP协议:若未指定绑定操作,可以通过下面connect操作来由内核负责套接字的绑定操作。内核会根
据套接字中的目的地址来判断外出接口,然后指定该外出接口的IP地址为插口的本地地址。connect操作对于TCP协议的客户端是必不可少的,必须指定。
4. 非阻塞的 socket connect
- 非阻塞模式有3种用途
- 三次握手同时做其他的处理。connect要花一个往返时间完成,从几毫秒的局域网到几百毫秒或几秒的广域网。这段时间可能有一些其他的处理要执行,比如数据准备,预处理等。
- 用这种技术建立多个连接。这在web浏览器中很普遍.
- 由于程序用select等待连接完成,可以设置一个select等待时间限制,从而缩短connect超时时间。多数实现中,connect的超时时间在75秒到几分钟之间。有时程序希望在等待一定时间内结束,使用非阻塞connect可以防止阻塞75秒,在多线程网络编程中,尤其必要。 例如有一个通过建立线程与其他主机进行socket通信的应用程序,如果建立的线程使用阻塞connect与远程通信,当有几百个线程并发的时候,由于网络延迟而全部阻塞,阻塞的线程不会释放系统的资源,同一时刻阻塞线程超过一定数量时候,系统就不再允许建立新的线程(每个进程由于进程空间的原因能产生的线程有限),如果使用非阻塞的connect,连接失败使用select等待很短时间,如果还没有连接后,线程立刻结束释放资源,防止大量线程阻塞而使程序崩溃