Linux 三种Socket网络通信模型(多进程、多线程、I\O复用)性能测试

Linux 三种Socket网络通信模型(多进程、多线程、I\O复用)性能测试

服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有循环服务器和并发服务器。

目前最常用的服务器模型有:

	·循环服务器:服务器在同一时刻只能响应一个客户端的请求

	·并发服务器:服务器在同一时刻可以响应多个客户端的请求

一个好的服务器,一般都是并发服务器(同一时刻可以响应多个客户端的请求)。并发服务器设计技术一般有:多进程服务器、多线程服务器、I/O复用服务器等。
本文实现三种Socket网络通信模型(多进程、多线程、I\O复用),并进行对比分析。

测试步骤:
1.分别编写3种socket网络通信服务器模型:多进程、多线程、I\O复用(select、epoll)。并测试通信是否正常。
2.编写shell脚本文件MultClient.sh,模拟100个客户器多并发。
3.编写shell脚本CountKillClient.sh,统计有客户端连接成功数量,并关闭相应客户端。
4.测试不同模型同时连接多少个客户端。
5.分析模型。

1.分别编写三种socket网络通信服务器模型:多进程、多线程、I\O复用(select、epoll)。并测试通信是否正常。
源码上传至:https://gitee.com/zhaoyuxinHIT/projects

2.编写shell脚本文件MultClient.sh,模拟N个客户器多并发。

#!/bin/sh

myfile="/home/zhaoyuxin/SocketTest/client/countsuc.log"

if [[ -f "$myfile" ]]; then
    rm -f $myfile
fi

starttime=`date +'%Y-%m-%d %H:%M:%S'`

echo "多客户端并发 N=3000"
#模拟3000个客户端
for i in {1..3000}
do
    ./socket_client & 
done

endtime=`date +'%Y-%m-%d %H:%M:%S'`
start_seconds=$(date --date="$starttime" +%s);
end_seconds=$(date --date="$endtime" +%s);

echo "本次运行时间: "$((end_seconds-start_seconds))"s"

3.编写shell脚本CountKillClient.sh,统计有客户端连接成功数量,并关闭相应客户端。

#! /bin/sh

echo "client连接数量:" $(ps aux | grep socket_client | grep -v grep | wc -l)

kill -9 $(ps -ef|grep ./socket_client|grep -v grep|awk '{print $2}')

4.测试不同模型同时连接3000个客户端。

bash MultiClient.sh
bash CountKillClient.sh

测试结果:
多进程模型:3000个
多线程模型:约1355个
Select模型:约1000个
Epoll模型:3000个

5.分析模型:

  1. 多进程模型:
    在 Linux 环境下多进程的应用很多,其中最主要的就是网络/客户服务器。多进程服务器是当客户有请求时,服务器用一个子进程来处理客户请求。父进程继续等待其它客户的请求。这种方法的优点是当客户有请求时,服务器能及时处理客户,特别是在客户服务器交互系统中。对于一个 TCP 服务器,客户与服务器的连接可能并不马上关闭,可能会等到客户提交某些数据后再关闭,这段时间服务器端的进程会阻塞,所以这时操作系统可能调度其它客户服务进程,这比起循环服务器大大提高了服务性能。

    TCP 并发服务器的思想是每一个客户机的请求并不由服务器直接处理,而是由服务器创建一个子进程来处理

    //多进程服务器模板
    #include <>
    int main()
    {
    	sockfd = socket(...)
    	bind(...)
    	listen(...)
    	while(1)
    	{
    		int connfd = accept(...);
    		pid = fork();
    		if(pid < 0)
    		if(pid > 0)//父进程
    		{
    			close(client_fd);
    			continue;
    		}
    		else if (pid == 0)//子进程
    		{
    			close(sockfd);
    			fun();//用于客户端操作
    			close(client_fd);
    			exti(0);
    		}
    	}
    	close(sockfd)
    }
    
  2. 多线程模型:
    多线程服务器是对多进程的服务器的改进,由于多进程服务器在创建进程时要消耗较大的系统资源,所以用线程来取代进程,这样服务处理程序可以较快的创建。据统计,创建线程与创建进程要快 10100 倍,所以又把线程称为“轻量级”进程。线程与进程不同的是:一个进程内的所有线程共享相同的全局内存、全局变量等信息,这种机制又带来了同步问题。

    //多线程服务器模板
    #include <>
    int main()
    {
    	sockfd = socket(...)
    	bind(...)
    	listen(...)
    	while(1)
    	{
    		int connfd = accept(...);
    		pthread_t thread_id;
    		pthread_create(&tid, NULL, thread_workbody, (void *)connfd);
    		pthread_detach(tid);
    	 }
    	close(sockfd)
    }
    void *thread_workbody(void *arg)
    {
    	int connfd = (int)arg;
    	fun(); //用于客户端操作
    	close(connfd);
    }
    
  3. I\O复用:
    I/O 复用技术是为了解决进程或线程阻塞到某个 I/O 系统调用而出现的技术,使进程不阻塞于某个特定的 I/O 系统调用。I/O 多路复用的最大优势是系统开销小,系统不需要建立新的进程或者线程,也不必维护这些线程和进程。

    1. select:
    //select()服务器模板
    #include <>
    int main()
    {
    	sockfd = socket(...)
    	bind(...)
    	listen(...)
    	
    	memset(&fds_array, -1, sizeof(fds_array));//初始化fds_array数组
    	fds_array[0] = listenfd;//第一个监听套接字
    	
    	while(1)  
    	{  
    		if(select(...) > 0) // 检测监听套接字是否可读  
    		{  
        		if(FD_ISSET(...)>0) // 套接字可读,证明有新客户端连接服务器    
        		{  
            		accpet(...);// 取出已经完成的连接  
            		fun(...);// 处理请求,反馈结果  
        		}  
    		}  
    		close(...); // 关闭连接套接字:accept()返回的套接字  
    	} 
    	close(sockfd)
    }
    
    
    1. epoll:
    //select()服务器模板
    #include <>
    int main()
    {
    	sockfd = socket(...)
    	bind(...)
    	listen(...)
    	
    	epollfd = epoll_create(MAX_EVENTS)
    	epoll_ctl(..)
    	while(1)
    	{
    		events = epoll_wait(...);
    		for(i = 0; i < events; i++)
    		{
    			if(event_array[i].data.fd == listenfd)//新的客户端建立连接
    			{
    				connfd = accept(...);
    				epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &event);
    			}
    			else // 客户端操作
    			{
    				fun();
    				epoll_ctl(epollfd, EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
    				close(event_array[i].data.fd);
    			}
    		}
    	}
    	close(sockfd)
    }
    
    
发布了6 篇原创文章 · 获赞 0 · 访问量 550

猜你喜欢

转载自blog.csdn.net/qq_29973657/article/details/97627308