一般linux下TCP连接的限制在TD_SETSIZE,系统默认为1024,由FD_SETSIZE决定。
1.修改方法:
修改/usr/etc/security/limits.conf文件,加入
* soft nofile 20000
* hard nofile 20000
然后reboot系统。
服务器就可以建立连接到20000个了,其连接方法是直接用connect,accept,注意这里用select是不可以的。
2.上面的方法在不用select方法的情况下是不可以的,如果你用select,那么仍然只能打开1024个,这是因为select的数目由FD_SETSIZE决定的。那么我们可以改用poll来替代select,poll数组大小可以根据我们自己的需要来定义,这样就解决了这个问题。
3.linux中的是通过文件方式来管理系统的,因此系统能承载多少TCP连接和系统文件打开数目能力是相关的。
另外在/proc/sys/file-max中定义了,系统最多能够打开的文件数目。
附代码:
服务器端:pollserver.cpp
#include <iostream>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/types.h>
//#include <asm/poll.h>
#include <netdb.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <sys/poll.h>
#include <limits.h> /* for OPEN_MAX */
#define LPORT 3333
#define LISTENQ 1024
#define OPEN_MAX 50000
#define MAX_LINE 100
void setnonblocking(int sock)
{
int opts;
opts=fcntl(sock,F_GETFL);
if(opts<0)
{
perror("fcntl(sock,GETFL)");
exit(1);
}
opts = opts|O_NONBLOCK;
if(fcntl(sock,F_SETFL,opts)<0)
{
perror("fcntl(sock,SETFL,opts)");
exit(1);
}
}
int main(int argc, char **argv)
{
//int i, maxi, listenfd, connfd, sockfd;
//int nready; ssize_t n;
int listenfd;
struct sockaddr_in cliaddr; //客户端的sock描述
struct sockaddr_in servaddr; //服务器的sock描述
struct pollfd *array_conn;
array_conn = new pollfd[OPEN_MAX];
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket create error!");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(LPORT);
/* 置 socket 重新使用 */
int opt = 1;
if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(char *) &opt,sizeof(opt))<0)
{
close(listenfd);
perror("!cserver::init_comm() setsockopt error!");
exit(1);
}
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr))== -1)
{
perror("bind error!");
exit(1);
}
listen(listenfd, LISTENQ);
array_conn[0].fd = listenfd;
array_conn[0].events = POLLRDNORM;
int i;
for ( i = 1; i < OPEN_MAX; i++) array_conn[i].fd = -1; /* -1 indicates available entry */
int maxi = 0;
int connfd;
int nready;
int clilen;
size_t n;
int x; x=0;
for ( ; ; ) {
int nready = poll(array_conn, maxi+1, 0);
if (array_conn[0].revents & POLLRDNORM)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr,(socklen_t*) &clilen);
printf(" ||%d: Connection from %s:%d\n",x++, inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
// setnonblocking(connfd);
for (i = 1; i < OPEN_MAX; i++)
if (array_conn[i].fd < 0)
{
array_conn[i].fd = connfd; // save descriptor
break;
}
if (i == OPEN_MAX)
{
printf("too many clients");
break;
}
array_conn[i].events = POLLRDNORM;
if (i > maxi) maxi = i;
if (--nready <= 0) continue; /* no more readable descriptors */
}
char line[100];
int sockfd;
for (i = 1; i <= maxi; i++)
{ /* check all clients for data */
if ( (sockfd = array_conn[i].fd) < 0) continue;
if (array_conn[i].revents & (POLLRDNORM | POLLERR))
{
if ( (n = read(sockfd, line, MAX_LINE)) < 0)
{
if (errno == ECONNRESET)
{
/*4connection reset by client */
close(sockfd);
array_conn[i].fd = -1;
} else
{
printf("readline error\n");
}
}
else if (n == 0)
{
/*4connection closed by client */
close(sockfd);
array_conn[i].fd = -1;
} else
{
char sb[10];
printf("Recv:%s from socket %d",line,sockfd);
sprintf(sb,"Pong!");
write(sockfd, sb, 10);
}
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}
客户端pollclient.cpp
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main()
{
int sockfd;
int address_len;
int connect_flag;
struct sockaddr_in address;
int connect_result;
char client_ch,server_ch;
int *sock;
sock= new int [50000];
int index=0;
int n=0;
int ssock;
address.sin_family=AF_INET;
address.sin_addr.s_addr=inet_addr("192.168.1.249");
address.sin_port=htons(3333);
address_len=sizeof(address);
while(1)
{
ssock=socket(AF_INET,SOCK_STREAM,0);
if(ssock<0)
{
printf("local sockfd error \n");
break;
}
connect_flag=connect(ssock,(struct sockaddr *)&address,address_len);
if(connect_flag==-1)
{
perror("client");
break;
}
printf("%d Connected! ",n++);
char cch[10];
sprintf(cch,"Ping*");
write(ssock,cch,10);
char rbuf[100];
read(ssock,rbuf,100);
printf( "%d Receive from server ;%s\n",n,rbuf);
//char c_ch;
//c_ch='*';
//write(ssock,&c_ch,1);
//char rbuf[100];
//read(ssock,rbuf,100);
//printf( "%d Receive from server ;%s\n",n,rbuf);
}
delete [] sock;
return 0;
}