一、select程序测试
首先启动,UNP程序目录下的tcpcliserv/tcpservselect01.c,当然首先需要编译,UNP每个目录下,都写有Makefile文件,make自动编译一下就可以了。然后运行以下客户端程序;
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SERV_PORT 9877 /* TCP and UDP */
#define MAXLINE 4096 /* max text line length */
void main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
int count = 0;
if (argc != 2) {
perror("usage : tcpcli <ipaddress>");
exit(0);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
for (;;) {
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("socket error: ");
exit(0);
}
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("connect error: ");
exit(0);
}
printf("the connect count is %d\n", count++);
}
}
运行结果:
zal@zal:~/NetBeansProjects/6-17$ ./client 127.0.0.1
。。。。。
the connect count is 1019
the connect count is 1020
socket error: : Too many open files
原因:
linux下每个进程最大开启的文件描述符为1024, 0 1 2占用3个文件描述符,但是应该还有一个描述符号可以用啊?什么原因?思考中。。。。
找到原因了:是计数count的问题,输出的时候count++; 应该改为++count;
zal@zal:~/NetBeansProjects/6-17$ ulimit -n
1024
服务器端运行结果:
。。。。。
new client: 127.0.0.1, port 44600
client count = 1019
client close
new client: 127.0.0.1, port 44601
client count = 1020
client close
new client: 127.0.0.1, port 44449
client count = 1021
client close
client close
原因分析:服务器端并没有由于FD_SETSIZE的限制而结束进程,由输出可知在accept的过程中有客户端连接结束,是因为客户端程序结束时,向服务器发送大量FIN,在accept的过程中已经又客户端结束,空出了描述符。因此并没有真正的实现并发。
解决方法:
为了使客户端程序结束时,不要集中发送FIN,需要休眠一段事件,让accept取出就绪队列中的所有连接。所以:
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
sleep(5);
perror("socket error: ");
exit(0);
}
在建立1022的socket出错时,休眠5秒,让服务器端accept完毕。结果如下:
new client: 127.0.0.1, port 46652
client count = 1019
new client: 127.0.0.1, port 46653
client count = 1020
accept error: Too many open files
原因分析: 服务器端由于描述符号达到限制,运行结束,客户端连接拒绝。但是限制应该是1024, 由于0 1 2 占用3个文件描述符,还有监听描述符,并发最大数应该为1020。这时由于每个进程的能够打开的最大文件描述符,并不是由于FD_SETSIZE;使用 ulimit -n 1030,将限制改大。看运行结果:
。。。。
new client: 127.0.0.1, port 47674
client count = 1020
new client: 127.0.0.1, port 47675
client count = 1021
*** buffer overflow detected ***: ./tcpservselect01 terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x63)[0xb7664bc3]
/lib/i386-linux-gnu/libc.so.6(+0x10593a)[0xb766393a]
/lib/i386-linux-gnu/libc.so.6(+0x106aaa)[0xb7664aaa]
./tcpservselect01[0x80495b5]
。。。
原因分析:
当1021个客户端连接来时,缓冲区溢出,看服务器端程序,连接数并没有达到FD_SETSIZE,是哪里出错了呢?思考。。。
二、Poll测试
将每个进程的描述符限制改为4096,
先运行UNP的poll客户端程序
zal@zal:~/unpv13e/tcpcliserv$ ./tcpservpoll01
运行客户端程序结果(服务器端):
。。。
client count = 4088
new client: 127.0.0.1, port 53831
client count = 4089
new client: 127.0.0.1, port 53832
client count = 4090
new client: 127.0.0.1, port 53833
client count = 4091
new client: 127.0.0.1, port 53834
client count = 4092
accept error: Too many open files
结果分析:
并发连接能够达到4092,可以看出poll没有限制FD_SETSIZE,这根据内存能够存放下的文件描述符。