服务器模型
1、循环服务器
实现流程:
1)、服务器端从连接请求队列中提取请求,建立连接并返回已连接的套接字。
2)、服务器端通过以连接的套接字循环接收数据,处理并发给客户端,直到客户端关闭连接。
3)、服务器端关闭已连接的套接字,返回步骤 1)。
特点:
1.服务器采用循环嵌套实现,外层循环一次提取每个客户端的链接请求,建立TCP链接。内层循环接收连接并处理当前客户端的所有数据,知道客户端关闭连接。
如果当前客户端没有处理结束,其他客户端必须一直等待。
2.采用这种循环服务器端无法实现对多个客户端服务。适应于客户端连接时间短的情况。
3.同一时刻只能处理一个客户端的请求,一般很少使用
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
int main ()
{
//定义结构体变量,作为bind函数的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
int servFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( servFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//绑定地址信息
int ret = bind ( servFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "bind error!" );
close ( servFd );
return - 1 ;
}
printf ( "bind ok!\n" );
//创建监听队列
ret = listen ( servFd , 10 );
if ( ret < 0 )
{
perror ( "listen error!" );
close ( servFd );
return - 1 ;
}
printf ( "listening.....\n" );
while ( 1 )
{
//接收连接请求
int connFd = accept ( servFd , NULL , NULL );
if ( connFd < 0 )
{
perror ( "accept error!" );
close ( servFd );
return - 1 ;
}
printf ( "accept ok!\n" );
char buf [ 1024 ] = { 0 };
//接收消息
ret = recv ( connFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "recv error!" );
close ( servFd );
close ( connFd );
return - 1 ;
}
printf ( "recv from client: %s\n" , buf );
strcat ( buf , "+++" );
send ( connFd , buf , sizeof ( buf ), 0 );
//关闭套接字
close ( connFd );
sleep ( 10 );
}
close ( servFd );
return 0 ;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
int main ()
{
//定义结构体变量,作为bind函数的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
int servFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( servFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//绑定地址信息
int ret = bind ( servFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "bind error!" );
close ( servFd );
return - 1 ;
}
printf ( "bind ok!\n" );
//创建监听队列
ret = listen ( servFd , 10 );
if ( ret < 0 )
{
perror ( "listen error!" );
close ( servFd );
return - 1 ;
}
printf ( "listening.....\n" );
while ( 1 )
{
//接收连接请求
int connFd = accept ( servFd , NULL , NULL );
if ( connFd < 0 )
{
perror ( "accept error!" );
close ( servFd );
return - 1 ;
}
printf ( "accept ok!\n" );
char buf [ 1024 ] = { 0 };
//接收消息
ret = recv ( connFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "recv error!" );
close ( servFd );
close ( connFd );
return - 1 ;
}
printf ( "recv from client: %s\n" , buf );
strcat ( buf , "+++" );
send ( connFd , buf , sizeof ( buf ), 0 );
//关闭套接字
close ( connFd );
sleep ( 10 );
}
close ( servFd );
return 0 ;
}
客户端代码:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
int cliFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( cliFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//发起连接请求
int ret = connect ( cliFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "connect error!" );
close ( cliFd );
return - 1 ;
}
printf ( "connect ok!\n" );
char buf [ 1024 ] = "hello world" ;
//发送消息
ret = send ( cliFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "send error!" );
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
int cliFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( cliFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//发起连接请求
int ret = connect ( cliFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "connect error!" );
close ( cliFd );
return - 1 ;
}
printf ( "connect ok!\n" );
char buf [ 1024 ] = "hello world" ;
//发送消息
ret = send ( cliFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "send error!" );
close(cliFd);
return -1;
}
printf("send ok!\n");
memset(buf, 0, sizeof(buf));
recv(cliFd, buf, sizeof(buf), 0);
printf("recv from server %s\n", buf);
//关闭套接字
close(cliFd);
return 0;
}
2
、并发服务器
>>>多进程的并发服务器
>>>多线程的并发服务器
>>>IO多路复用的并发服务器
>>>多进程的并发服务器
>>>多线程的并发服务器
>>>IO多路复用的并发服务器
>>>多进程的并发服务器
只要有客户端连接服务器,服务器就创建子进程与客户端通信
创建子进程后,父进程----继续等待其他客户端的连接
子进程----与客户端通信
总结:多进程服务器,比较浪费资源,适合于客户端数量较少,但是长连接的情况
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
void sigFunc ( int sigNo )
{
if ( sigNo == SIGCHLD )
{
wait ( NULL );
}
}
int main ()
{
//定义结构体变量,作为bind函数的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
int servFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( servFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//绑定地址信息
int ret = bind ( servFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "bind error!" );
close ( servFd );
return - 1 ;
}
printf ( "bind ok!\n" );
//创建监听队列
ret = listen ( servFd , 10 );
if ( ret < 0 )
{
perror ( "listen error!" );
close ( servFd );
return - 1 ;
}
printf ( "listening.....\n" );
while ( 1 )
{
//接收连接请求
int connFd = accept ( servFd , NULL , NULL );
if ( connFd < 0 )
{
perror ( "accept error!" );
close ( servFd );
return - 1 ;
}
printf ( "accept ok!\n" );
//创建子进程
pid_t pid ;
while (( pid = fork ()) < 0 );
if ( 0 == pid )
{
close ( servFd );
char buf [ 1024 ] = { 0 };
while ( 1 )
{
//接收消息
memset ( buf , 0 , sizeof ( buf ));
ret = recv ( connFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "recv error!" );
close ( connFd );
return - 1 ;
}
else if ( 0 == ret )
{
printf ( "client shutdown!\n" );
break ;
}
printf ( "recv from client: %s\n" , buf );
memset ( buf , 0 , sizeof ( buf ));
printf ( "server:" );
gets ( buf );
send ( connFd , buf , sizeof ( buf ), 0 );
}
//关闭套接字
close ( connFd );
exit ( 0 );
}
else
{
close ( connFd );
signal ( SIGCHLD , sigFunc );
}
}
close ( servFd );
return 0 ;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
void sigFunc ( int sigNo )
{
if ( sigNo == SIGCHLD )
{
wait ( NULL );
}
}
int main ()
{
//定义结构体变量,作为bind函数的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
int servFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( servFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//绑定地址信息
int ret = bind ( servFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "bind error!" );
close ( servFd );
return - 1 ;
}
printf ( "bind ok!\n" );
//创建监听队列
ret = listen ( servFd , 10 );
if ( ret < 0 )
{
perror ( "listen error!" );
close ( servFd );
return - 1 ;
}
printf ( "listening.....\n" );
while ( 1 )
{
//接收连接请求
int connFd = accept ( servFd , NULL , NULL );
if ( connFd < 0 )
{
perror ( "accept error!" );
close ( servFd );
return - 1 ;
}
printf ( "accept ok!\n" );
//创建子进程
pid_t pid ;
while (( pid = fork ()) < 0 );
if ( 0 == pid )
{
close ( servFd );
char buf [ 1024 ] = { 0 };
while ( 1 )
{
//接收消息
memset ( buf , 0 , sizeof ( buf ));
ret = recv ( connFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "recv error!" );
close ( connFd );
return - 1 ;
}
else if ( 0 == ret )
{
printf ( "client shutdown!\n" );
break ;
}
printf ( "recv from client: %s\n" , buf );
memset ( buf , 0 , sizeof ( buf ));
printf ( "server:" );
gets ( buf );
send ( connFd , buf , sizeof ( buf ), 0 );
}
//关闭套接字
close ( connFd );
exit ( 0 );
}
else
{
close ( connFd );
signal ( SIGCHLD , sigFunc );
}
}
close ( servFd );
return 0 ;
}
客户端代码:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
int cliFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( cliFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//发起连接请求
int ret = connect ( cliFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "connect error!" );
close ( cliFd );
return - 1 ;
}
printf ( "connect ok!\n" );
char buf [ 1024 ];
while ( 1 )
{
memset ( buf , 0 , sizeof ( buf ));
printf ( "client:" );
gets ( buf );
if ( 0 == strcmp ( buf , "quit" ))
{
break ;
}
//发送消息
ret = send ( cliFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "send error!" );
close ( cliFd );
return - 1 ;
}
printf ( "send ok!\n" );
memset ( buf , 0 , sizeof ( buf ));
recv ( cliFd , buf , sizeof ( buf ), 0 );
printf ( "recv from server %s\n" , buf );
}
//关闭套接字
close ( cliFd );
return 0 ;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
int cliFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( cliFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//发起连接请求
int ret = connect ( cliFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "connect error!" );
close ( cliFd );
return - 1 ;
}
printf ( "connect ok!\n" );
char buf [ 1024 ];
while ( 1 )
{
memset ( buf , 0 , sizeof ( buf ));
printf ( "client:" );
gets ( buf );
if ( 0 == strcmp ( buf , "quit" ))
{
break ;
}
//发送消息
ret = send ( cliFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "send error!" );
close ( cliFd );
return - 1 ;
}
printf ( "send ok!\n" );
memset ( buf , 0 , sizeof ( buf ));
recv ( cliFd , buf , sizeof ( buf ), 0 );
printf ( "recv from server %s\n" , buf );
}
//关闭套接字
close ( cliFd );
return 0 ;
}
>>>多线程的并发服务器
只要有客户端连接服务器,服务器就创建子线程与客户端通信
由于在创建子线程时,以及销毁子线程时,比较浪费时间,一般可以使用线程池
多线程存在的问题:存在资源竞争以及同步的问题
总结:适合于客户端数量较少,但是长连接的情况
只要有客户端连接服务器,服务器就创建子线程与客户端通信
由于在创建子线程时,以及销毁子线程时,比较浪费时间,一般可以使用线程池
多线程存在的问题:存在资源竞争以及同步的问题
总结:适合于客户端数量较少,但是长连接的情况
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
void * threadFunc ( void * arg )
{
int connFd = *(( int *) arg );
char buf [ 1024 ] = { 0 };
while ( 1 )
{
memset ( buf , 0 , sizeof ( buf ));
//接收消息
int ret = recv ( connFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "recv error!" );
close ( connFd );
pthread_exit (( void *)- 1 );
}
else if ( 0 == ret )
{
printf ( "client shutdown!\n" );
break ;
}
printf ( "recv from client: %s\n" , buf );
memset ( buf , 0 , sizeof ( buf ));
printf("server:");
gets(buf);
send(connFd, buf, sizeof(buf), 0);
}
close(connFd);
pthread_exit(NULL);
}
int main()
{
//定义结构体变量,作为bind函数的参数
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = PF_INET;
servAddr.sin_port = htons(8888);
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
int servFd = socket(PF_INET, SOCK_STREAM, 0);
if(servFd < 0)
{
perror("socket error!");
return -1;
}
printf("socket ok!\n");
//绑定地址信息
int ret = bind(servFd, (struct sockaddr *)&servAddr, sizeof(servAddr));
if(ret < 0)
{
perror("bind error!");
close(servFd);
return -1;
}
printf("bind ok!\n");
//创建监听队列
ret = listen(servFd, 10);
if(ret < 0)
{
perror("listen error!");
close(servFd);
return -1;
}
printf("listening.....\n");
while(1)
{
//接收连接请求
int connFd = accept(servFd, NULL, NULL);
if(connFd < 0)
{
perror("accept error!");
close(servFd);
return -1;
}
printf("accept ok!\n");
pthread_t th;
while(pthread_create(&th, NULL, threadFunc, &connFd) < 0);
}
//关闭套接字
close(servFd);
return 0;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
void * threadFunc ( void * arg )
{
int connFd = *(( int *) arg );
char buf [ 1024 ] = { 0 };
while ( 1 )
{
memset ( buf , 0 , sizeof ( buf ));
//接收消息
int ret = recv ( connFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "recv error!" );
close ( connFd );
pthread_exit (( void *)- 1 );
}
else if ( 0 == ret )
{
printf ( "client shutdown!\n" );
break ;
}
printf ( "recv from client: %s\n" , buf );
memset ( buf , 0 , sizeof ( buf ));
printf("server:");
gets(buf);
send(connFd, buf, sizeof(buf), 0);
}
close(connFd);
pthread_exit(NULL);
}
int main()
{
//定义结构体变量,作为bind函数的参数
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = PF_INET;
servAddr.sin_port = htons(8888);
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//创建套接字
//返回值为新创建的socket的文件描述符,失败-1
int servFd = socket(PF_INET, SOCK_STREAM, 0);
if(servFd < 0)
{
perror("socket error!");
return -1;
}
printf("socket ok!\n");
//绑定地址信息
int ret = bind(servFd, (struct sockaddr *)&servAddr, sizeof(servAddr));
if(ret < 0)
{
perror("bind error!");
close(servFd);
return -1;
}
printf("bind ok!\n");
//创建监听队列
ret = listen(servFd, 10);
if(ret < 0)
{
perror("listen error!");
close(servFd);
return -1;
}
printf("listening.....\n");
while(1)
{
//接收连接请求
int connFd = accept(servFd, NULL, NULL);
if(connFd < 0)
{
perror("accept error!");
close(servFd);
return -1;
}
printf("accept ok!\n");
pthread_t th;
while(pthread_create(&th, NULL, threadFunc, &connFd) < 0);
}
//关闭套接字
close(servFd);
return 0;
}
客户端代码:
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
int cliFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( cliFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//发起连接请求
int ret = connect ( cliFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "connect error!" );
close ( cliFd );
return - 1 ;
}
printf ( "connect ok!\n" );
char buf [ 1024 ];
while ( 1 )
{
memset ( buf , 0 , sizeof ( buf ));
printf ( "client:" );
gets ( buf );
if ( 0 == strcmp ( buf , "quit" ))
{
break ;
}
//发送消息
ret = send ( cliFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "send error!" );
close ( cliFd );
return - 1 ;
}
printf ( "send ok!\n" );
memset ( buf , 0 , sizeof ( buf ));
recv ( cliFd , buf , sizeof ( buf ), 0 );
printf ( "recv from server %s\n" , buf );
}
//关闭套接字
close ( cliFd );
return 0 ;
}
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main ()
{
//定义结构体变量,该变量保存的服务器的地址信息,作为connect的参数
struct sockaddr_in servAddr ;
memset (& servAddr , 0 , sizeof ( servAddr ));
servAddr . sin_family = PF_INET ;
servAddr . sin_port = htons ( 8888 );
servAddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
//创建套接字
int cliFd = socket ( PF_INET , SOCK_STREAM , 0 );
if ( cliFd < 0 )
{
perror ( "socket error!" );
return - 1 ;
}
printf ( "socket ok!\n" );
//发起连接请求
int ret = connect ( cliFd , ( struct sockaddr *)& servAddr , sizeof ( servAddr ));
if ( ret < 0 )
{
perror ( "connect error!" );
close ( cliFd );
return - 1 ;
}
printf ( "connect ok!\n" );
char buf [ 1024 ];
while ( 1 )
{
memset ( buf , 0 , sizeof ( buf ));
printf ( "client:" );
gets ( buf );
if ( 0 == strcmp ( buf , "quit" ))
{
break ;
}
//发送消息
ret = send ( cliFd , buf , sizeof ( buf ), 0 );
if ( ret < 0 )
{
perror ( "send error!" );
close ( cliFd );
return - 1 ;
}
printf ( "send ok!\n" );
memset ( buf , 0 , sizeof ( buf ));
recv ( cliFd , buf , sizeof ( buf ), 0 );
printf ( "recv from server %s\n" , buf );
}
//关闭套接字
close ( cliFd );
return 0 ;
}
>>>IO多路复用的并发服务器
适合于客户端数量较多,但是短连接的情况。
适合于客户端数量较多,但是短连接的情况。