并发服务器端程序设计实验报告
综合性、设计性实验项目简介
学院名称(公章): 学期 填表日期: 年 月 日
实验课程名称网络程 主要培养学生组织能力。设计并发策略的目的就是就是让IO操作和CPU计算尽量重叠进行。一方面要让CPU在IO等待不要空闲,另一方面要让CPU在IO调度上尽量花最少的时间。
(1)一个进程处理一个连接,非阻塞IO
这样会存在多个并发请求同时到达时,服务器必然要准备多个进程来处理请求。这种策略典型的例子就是Apache的fork和prefork模式。对于并发数不高的站点同时依赖Apache其它功能时的应用选择Apache还是可以的。
(2)一个线程处理一个连接,非阻塞IO
这种方式允许在一个进程中通过多个线程来处理多个连接,一个线程处理一个连接。Apache的worker模式就是这种典型例子,使其可支持更多的并发连接。不过这种模式的总体性能还不如prefork,所以一般不选用worker模式。
(3)一个进程处理多个连接,非阻塞IO
适用的前提条件就是多路IO就绪通知的应用。这种情况下,将处理多个连接的进程叫做worker进程或服务进程。worker的数量可以配置,如Nginx中的worker_processes 4
(4)一个线程处理多个连接,异步IO
即使有高性能的多路IO就绪通知,但磁盘IO的等待还是无法避免的。更加高效的方法是对磁盘文件使用异步IO,目前很少有Web服务器真正意义上支持这种异步IO。
#include
#include
#include
#include
#include
#include
#define MAXLINE 4096
int main( int argc , char * * argv )
{
int listenfd , connfd;
struct sockaddr_in servaddr;
char sendBuff[ MAXLINE ], recvBuff[ MAXLINE ];
time_t ticks;
pid_t pid;
listenfd = socket( AF_INET , SOCK_STREAM , 0 );
memset( &servaddr , 0 , sizeof( servaddr ) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( 10023 );//端口:10023 无法使用23号端口
bind( listenfd , (struct sockaddr *)&servaddr , sizeof( servaddr ) );
listen( listenfd , 1024 );
int i = 0;
for( ; ; )
{
printf("Start!\n");
connfd = accept( listenfd , (struct sockaddr *)NULL , NULL );
printf("Client ID: %d\n",i);//记录连接客户数量
if( (pid = fork()) == 0 )//多进程
{
close( listenfd );
sendBuff[0] = 0Xff;
sendBuff[1] = 0Xfb;
sendBuff[2] = 0X01;//Will Echo 命令
sendBuff[3] = 0Xff;
sendBuff[4] = 0Xfb;
sendBuff[5] = 0X03;//Will Suppress Go Ahead 命令
write( connfd , sendBuff , 6 );
read( connfd, recvBuff, MAXLINE );//读取回传值,本实验中丢弃
ticks = time( NULL );
snprintf( sendBuff , sizeof( sendBuff ) , "\r\nWelcome to 10023 port Telnet Server!\r\nTime of server: %.24s\r\n" , ctime( &ticks ) );
write( connfd , sendBuff , strlen( sendBuff ) );//发送欢迎信息