提高Linux的连接限制

一般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.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.fd < 0)
    {
     array_conn.fd = connfd; // save descriptor
     break;
    }
    if (i == OPEN_MAX)
    {
     printf("too many clients");
     break;
    }
    array_conn.events = POLLRDNORM;
    if (i > maxi) maxi = i;  
    if (--nready <= 0) continue; /* no more readable descriptors */
  }

  /* check all clients for data */
     char line[100];
  int sockfd;
  for (i = 1; i <= maxi; i++)
  { /* check all clients for data */
   if ( (sockfd = array_conn.fd) < 0) continue;
   if (array_conn.revents & (POLLRDNORM | POLLERR))
   {
    if ( (n = read(sockfd, line, MAX_LINE)) < 0)
    {
     if (errno == ECONNRESET)
     {
      /*4connection reset by client */
      close(sockfd);
      array_conn.fd = -1;
     } else
     {
      printf("readline error\n");
     }
    }
    else if (n == 0)
    {
     /*4connection closed by client */
     close(sockfd);
     array_conn.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;
}