读alhttpd有感

读了下althttpd的源代码,想研究下 one-process-one-connection 模型的服务器具体是咋实现,结果核心代码也就 20 来行(省略了外头的while(1)和变量声明):

select( maxFd+1, &readfds, 0, 0, &delay);
for(i=0; i<n; i++){
  if( FD_ISSET(listener[i], &readfds) ){
    lenaddr = sizeof(inaddr);
    connection = accept(listener[i], &inaddr.sa, &lenaddr);
    if( connection>=0 ){
      child = fork();
      if( child!=0 ){
        if( child>0 ) nchildren++;
        close(connection);
        printf("subprocess %d started...\n", child); fflush(stdout);
      }else{
        int nErr = 0, fd;
        close(0);
        fd = dup(connection);
        if( fd!=0 ) nErr++;
        close(1);
        fd = dup(connection);
        if( fd!=1 ) nErr++;
        close(connection);
        return nErr;
      }
    }
  }
}

流程异常简单:

  1. 父进程:select => accept => 计数 => 关闭 connection 的 fd => select
  2. 子进程:把 stdinstdout 都替换成 connection 的 fd => 跳出循环 => 处理 req/res

先不考虑多进程带来的性能问题,这个设计实在是简洁和漂亮:子进程直接读stdin处理 request;子进程直接写stdout处理 response;子进程遇到异常直接exit就 OK 了,没有 leak 烦恼,安全性也好处理,还不影响主进程继续处理后续请求。

原谅我没咋度过 linux 的服务器源代码,直接把子进程的stdinstdout替换成 socket fd 这个设计还是让我“大惊小怪”了一把,everything is file yyds!设计 Unix 的先贤们 yyds!