前面通过IO复用实现了 connect
的定时, 本节使用 connect
非阻塞验证进程 能保持多少 TCP连接.
非阻塞式
非阻塞 connect
还能用来测试服务端的抗压能力, 当然使用阻塞 connect
也能够保持多个 TCP 连接, 但效率没有非阻塞高. 可以看出来同一时间阻塞式的必须保证一个连接成功才会执行后一个连接, 非阻塞式能够在同一时间保证多个连接的进行.
完整代码 : client.c
部分重要代码 :
// connect 分为三种状态
#define F_CONNECTING 1 /* connect 正在连接中 */
#define F_CONNECTED 2 /* connect 连接成功 */
#define F_READING 4 /* 正在读数据, 该状态未用 */
// 保存文件描述符和状态信息
struct file{
char buf[BUFSZIE];
int fd;
int stat;
socklen_t len;
struct sockaddr_in addr;
}file[SOCKSIZE];
// 非阻塞连接
int nonblock_connect(){
int sockfd, oldfd;
struct epoll_event event;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd >= SOCKSIZE || socket < 0){
close(sockfd);
fprintf(stderr, "socket error");
return -1;
}
// 设置非阻塞
oldfd = setnonblock(sockfd);
initfile(sockfd);
done:
if(connect(sockfd, (struct sockaddr *)&file[sockfd].addr, file[sockfd].len) < 0){
if(errno != EINPROGRESS){
printf("%d ", errno);
close(sockfd);
perror("connect error");
exit(1);
}
goto done;
}
file[sockfd].stat = F_CONNECTING; // 设置 connect 当前状态, 正在连接中
event.events = EPOLLIN | EPOLLOUT;
event.data.fd = sockfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &event);
return 0;
}
多进程验证
服务端 : fork_service.c
./service 8080
客户端 : (第三个参数表示连接的TCP个数)
./client 127.0.0.1 8080 9000
通过上一篇文章先设置号 最大打开文件描述符.
运行结果 :
看出来本机多进程最多能够允许打开4979个 TCP 连接.
IO复用验证
服务端 : IO_service.c
./service 8080
客户端 : (第三个参数表示连接的TCP个数)
./client 127.0.0.1 8080 9000
要切换到 root 下运行, 不明白的可以看 最大打开文件描述符[1].
运行结果 :
通过 lsof
命令查看服务端进程的连接个数 :
最终截图到的是IO复用大概支持 16000 到 17000 之间个 TCP连接.
小结
- 非阻塞式 connect 比阻塞式在相同时间能够建立更多的连接
- web 客户端通常就采用 非阻塞式.