前言
關(guān)于TCP服務(wù)器最大并發(fā)連接數(shù)有一種誤解就是“因為端口號上限為65535,所以TCP服務(wù)器理論上的可承載的最大并發(fā)連接數(shù)也是65535”。
先說結(jié)論:對于TCP服務(wù)端進程來說,他可以同時連接的客戶端數(shù)量并不受限于可用端口號。并發(fā)連接數(shù)受限于linux可打開文件數(shù),這個數(shù)是可以配置的,可以非常大,所以實際上受限于系統(tǒng)性能。
現(xiàn)在做服務(wù)器開發(fā)不加上高并發(fā)根本沒臉出門,所以為了以后吹水被別人懟“天天提高并發(fā),你自己實現(xiàn)的最高并發(fā)是多少”的時候能義正言辭的懟回去,趁著元旦在家沒事決定自己寫個demo搞一搞。
這個測試主要是想搞明白Linux下哪些參數(shù)配置限制了連接數(shù)的最大值,上限是多少。
一、先說下demo的思路:
服務(wù)端用epoll實現(xiàn),就是簡簡單單的接收連接,然后客戶端用go的goroutine,每個goroutine就是簡單的建立連接,然后什么也不做。
上代碼:
server:
/* * g++ -o test_epoll ./test_epoll.c */#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/epoll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>int SetReuseAddr(int fd){ int optval = 1; socklen_t optlen = sizeof(optval); return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);}int main(){ int fd = socket(AF_INET, SOCK_STREAM, 0); int iRet = SetReuseAddr(fd); if (iRet != 0) { printf("setsockopt for SO_REUSEADDR failed, error:%s/n", strerror(iRet)); return iRet; } struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(8080); addr.sin_addr.s_addr = INADDR_ANY; if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { printf("bind failed, error:%s/n", strerror(errno)); return errno; } if (listen(fd, 5) == -1) { printf("listen failed, error:%s/n", strerror(errno)); return errno; } printf("Listening on 8080.../n"); int epfd = epoll_create(102400); struct epoll_event event; event.events = EPOLLIN; event.data.fd = fd; epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); struct epoll_event revents[102400]; int iOnline = 0; while (1) { int num = epoll_wait(epfd, revents, 102400, 60 * 1000); printf("epoll_wait return %d/n", num); if (num > 0) {  for (int i = 0; i < num; i++)  {  if (revents[i].data.fd == fd)  {   int client;   struct sockaddr_in cli_addr;   socklen_t cli_addr_len = sizeof(cli_addr);   client = accept(fd, (struct sockaddr*)&cli_addr, &cli_addr_len);   if (client == -1)   {   printf("accept failed, error:%s/n", strerror(errno));   if (errno == EMFILE)   {    printf("per-process limit reached/n");    exit(errno);   }   if (errno == ENFILE)   {    printf("system-wide limit reached/n");    exit(errno);   }   continue;   }   iOnline++;   printf("Receive a new connection from %s:%d/n", inet_ntoa(cli_addr.sin_addr), cli_addr.sin_port);   event.events = EPOLLIN;   event.data.fd = client;   epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);  }  } } printf("Online number:%d/n", iOnline); } return 0;}
新聞熱點
疑難解答
圖片精選