前言:
而今我们对“服务器的测试”大概比较重视,朋友们都需要知道一些“服务器的测试”的相关资讯。那么小编同时在网摘上收集了一些对于“服务器的测试””的相关文章,希望小伙伴们能喜欢,你们一起来学习一下吧!有压力测试程序有很多种实现方式,比如I/O复用方式,多线程、多进程并发编程方式,以及这些方式的结合使用。不过单纯的I/O复用方式的施压程度是最高的,因为线程和进程的调度本身也要占用一定的CPU时间的。因此,我们将使用epoll来实现一个通用的服务器压力测试程序,示例代码如下:
#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <unistd.h>#include <sys/types.h>#include <sys/epoll.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>/*每个客户连接不停地向服务器发送这个请求*/static const char* request = "GET HTTP/1.1\r\nConnection:keep-alive\r\nxxxxxxxxxxxxxx";int setnonblocking(int fd){ int old_option = fcntl(fd, F_GETFL); int new_option = old_option | O_NONBLOCK; fcntl(fd, F_SETFL, new_option); return old_option;}void addfd(int epoll_fd, int fd){ epoll_event event; event.data.fd = fd; event.events = EPOLLOUT|EPOLLET|EPOLLERR; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event); setnonblocking(fd);}/*向服务器写入len字节的数据*/bool write_nbutes(int sockfd, const char* buffer, int len){ int bytes_write = 0; printf("write out %d bytes to socket %d\n", len, sockfd); while(1){ bytes_write = send(sockfd, buffer, len, 0); if(bytes_write == -1){ return false; } else if(bytes_write == 0){ return false; } len -= bytes_write; buffer = buffer + bytes_write; if(len < 0){ return true; } }}/*从服务器读取数据*/bool read_once(int sockfd, char* buffer, int len){ int bytes_read = 0; memset(buffer, '\0', len); bytes_read = recv(sockfd, buffer, len, 0); if(bytes_read == -1){ return false; } else if(bytes_read == 0){ return false; } printf("read in %d bytes from socket %d with content: %s\n", bytes_read, sockfd, buffer); return true;}/*向服务器发起num个TCP连接,我们可以通过改变num来调整压力测试*/void start_conn(int epoll_fd, int num, const char* ip, int port){ int ret = 0; struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET, ip, &address.sin_addr); address.sin_port = htons(port); for(int i = 0; i < num; ++i){ sleep(1); int sockfd = socket(PF_INET, SOCK_STREAM, 0); printf("create 1 sock\n"); if(sockfd < 0){ continue; } if(connect(sockfd, (struct sockaddr*)&address, sizeof(address)) == 0){ printf("build connection %d\n", i); addfd(epoll_fd, sockfd); } }}void close_conn(int epoll_fd, int sockfd){ epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sockfd, 0); close(sockfd);}int main(int argc, char const *argv[]){ assert(argc == 4); int epoll_fd = epoll_create(100); start_conn(epoll_fd, atoi(argv[3]), argv[1], atoi(argv[2])); epoll_event events[10000]; char buffer[2048]; while(1){ int fds = epoll_wait(epoll_fd, events, 10000, 2000); for(int i = 0; i< fds; ++i){ int sockfd = events[i].data.fd; if(events[i].events & EPOLLIN){ if(!read_once(sockfd, buffer, 2048)){ close_conn(epoll_fd, sockfd); } struct epoll_event event; event.events = EPOLLOUT | EPOLLET | EPOLLERR; event.data.fd = sockfd; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sockfd, &event); } else if(events[i].events & EPOLLOUT){ if(!write_nbutes(sockfd, request, strlen(request))){ close_conn(epoll_fd, sockfd); } struct epoll_event event; event.events = EPOLLIN | EPOLLET | EPOLLERR; event.data.fd = sockfd; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sockfd, &event); } else if(events[i].events & EPOLLERR){ close_conn(epoll_fd, sockfd); } } } return 0;}
下面考虑将使用该压力程序测试(名为stress_test)来测试进程池和线程池 - 用线程池实现的简单Web服务器一文中所描述的Web服务器的稳定性,我们先在一台机器上运行websrv,然后在另一台机器上运行stress_test,向websrv服务器发起1000个连接,具体操作如下:
$ ./websrv 10.0.0.199 12345 #启动web server,监听端口12345
$ ./stress_test 10.0.0.199 12345 1000
如果websrv服务器程序足够稳定,那么websrv和stress_test这两个程序将一直运行下去,并不断交换数据。
版权声明:
本站文章均来自互联网搜集,如有侵犯您的权益,请联系我们删除,谢谢。
标签: #服务器的测试