在第一节的例子中,服务器是一个时间获取程序,只要一次write调用就能立刻完成客户端的任务,但是我们要想的是,服务端不一定每次都会这么快的完成任务,所以,要想办法加快服务端的处理速度。
首先可以想到的是并行处理,c++有两种方式,一个是多进程,一个是多线程。下面描述这两种办法。
一、压力测试
我们的客户端应当有能力判断服务端处理的快慢,所以我们要写一个压力测试函数:
void request_to_server(int id,const char* ip,const uint16_t port){
int sockfd=socket(AF_INET,SOCK_STREAM,0);
const char *id_str=std::to_string(id).c_str();
sockaddr_in addr;
bzero(&addr,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_port=htons(port);
inet_pton(AF_INET,ip,&addr.sin_addr);
connect(sockfd,(const sockaddr*)&addr,sizeof(addr));
const int buffersize=1024;
char buf[buffersize];
write(sockfd,id_str,strlen(id_str));
cout<<"has sended id="< threads;
for(int i=0;i
压力测试函数利用多线程,指定用户数和每个用户发起的请求数,可以计算出总的处理时间。
对于我们前面的时间服务器程序——一个迭代处理方式(也就是最慢的那种),我们用100个用户发起10次请求/人。
输出:
answer message(89):Sun Jan 12 19:25:44 2020
answer message(96):Sun Jan 12 19:25:44 2020
answer message(41):Sun Jan 12 19:25:44 2020
all task finish. used time=430 ms
上面是返回数据的一部分,下面是计算得到的总时间是430ms。
二、慢服务器
1、迭代做法
void slow_handle_function(int id=0){
cout<<"start processing... -"<
首先我们有这么一个很慢的函数,要花费3秒才能完成。
void server1(){
const uint16_t listened_port=9000;
const char* localhost="127.0.0.1";
const int listening_queue_length=1024;
const int buffersize=1024;
int listen_fd=socket(AF_INET,SOCK_STREAM,0);
sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
in_addr temp;
inet_pton(AF_INET,localhost,&server_addr.sin_addr);
//server_addr.sin_addr.s_addr=htonl(temp.s_addr);
server_addr.sin_port=htons(listened_port);
bind(listen_fd,(const sockaddr*)&server_addr,sizeof(server_addr));
listen(listen_fd,listening_queue_length);
char buffer[buffersize];
while(1){
sockaddr_in client_addr;
socklen_t len=sizeof(client_addr);
cout<<"wating for a connection..."<void server2(){
const uint16_t listened_port=9000;
const char* localhost="127.0.0.1";
const int listening_queue_length=1024;
const int buffersize=1024;
int listen_fd=socket(AF_INET,SOCK_STREAM,0);
sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
in_addr temp;
inet_pton(AF_INET,localhost,&server_addr.sin_addr);
//server_addr.sin_addr.s_addr=htonl(temp.s_addr);
server_addr.sin_port=htons(listened_port);
bind(listen_fd,(const sockaddr*)&server_addr,sizeof(server_addr));
listen(listen_fd,listening_queue_length);
char buffer[buffersize];
pid_t pid;
while(1){
sockaddr_in client_addr;
socklen_t len=sizeof(client_addr);
cout<<"wating for a connection..."<void task_handle(int fd){
const int buffersize=1024;
char buffer[buffersize];
auto n=read(fd,buffer,buffersize);
buffer[n]='\0';
cout<<"get id="<
这里面使用了thread类的里面的detach方法,可以在后台用线程处理任务。
任务封装到一个函数里面,并且这次由子线程关闭描述符,测试结果如下:
answer message(10):10
answer message(9):9
answer message(8):8
all task finish. used time=15.0064 s
如果说15s之外的时间是计算机处理线程或者进程的时间,那么,虽然不是很明显,但的确可以看见多线程快于多进程!