现在的位置: 首页 > 综合 > 正文

在WebServer中如何实现CGI技术

2013年10月19日 ⁄ 综合 ⁄ 共 4485字 ⁄ 字号 评论关闭
谈谈WebServer中如何实现CGI技术
 
在WebServer中,cgi技术的实现相信许多人很感兴趣,不过在一些开源软件如Apache中,由于软件规模大,相关模块多,直接去读懂是如何实现的比较费劲,下面就来谈谈CGI技术的实现方法。
 
       要实现CGI技术,关键是要实现执行其他应用程序时,将应用程序的输出从屏幕重定向到SOCKET中去,实现了应用程序的输出重定向后,CGI实现就很简单了。
 
下面以windows平台为例来实现cgi技术。以下的cgi_writeclient()函数便实现了将CGI程序的输出结果重定向到socket的功能。
 
HANDLE cgi_exec( HANDLE hPipeWrite, char *exefile, char *cmdline, char *lpszCurrentPath )
{
    BOOL            bSucceed;
    STARTUPINFO         sui;
    PROCESS_INFORMATION pi;
    BOOL                bTest;
 
       memset(&sui,0,sizeof(STARTUPINFO));
       sui.cb=sizeof(STARTUPINFO);
        sui.dwXSize = 0;
        sui.dwXSize = 0;
        sui.wShowWindow = SW_HIDE;
       sui.dwFlags= STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
       sui.hStdInput=NULL;
       sui.hStdOutput=hPipeWrite;
       sui.hStdError=hPipeWrite;
 
       bSucceed = CreateProcess(exefile,
                     cmdline,
                     NULL,
                     NULL,
                     TRUE,
                     0,//CREATE_NEW_PROCESS_GROUP ,
                     NULL,
                     lpszCurrentPath,//lpszPath,//"//Rose//c//",//NULL,//"d:/ip_progs/namepipe/child",
                     &sui,
                     &pi);
       if ( bSucceed )
       {
              CloseHandle( pi.hThread );
              return pi.hProcess;
       }
//     ShowErrorMessage( "CreateProcess()" );
       return FALSE;
}
 
int cgi_writeclient( HTTPRequest *hr )
{
       char *pszPath;
       HANDLE hProcess;
       BOOL     bProcessDead = FALSE;
       HANDLE hPipeRead, hPipeWrite;
       SECURITY_ATTRIBUTES SecAttrib;
       int           ret;
       int        BytesInPipe;
       char *buf;
       DWORD dwRead;
 
       SecAttrib.nLength = sizeof(SECURITY_ATTRIBUTES);
       SecAttrib.lpSecurityDescriptor = NULL;
       SecAttrib.bInheritHandle = TRUE;
 
       if ( hr->http_mod != HTTP_GET )
       {
              return MODULE_RUN_CONTINUE;
       }
       if ( hr->mod != MOD_LOCAL )
       {
           return MODULE_RUN_CONTINUE;
       }
 
       pszPath = MemAlloc( hr->hMem, strlen( pszCgiRoot ) + strlen(hr->http_url) + 10 );
       if ( !pszPath )
       {
              return MODULE_RUN_CONTINUE;
       }
       /* decide if it is the cgi path */
       strcpy( pszPath, hr->http_url );
       if ( pszPath[strlen(pszPath)-1] == '/' )
       {
              if ( *(hr->http_url) == '/' )
              {
                     strcat( pszPath, hr->http_url+1 );
              }
              else
              {
                     strcat( pszPath, hr->http_url );
              }
       }
       else
       {
              strcpy( pszPath, pszRoot );
              strcat( pszPath, hr->http_url );
              ReplaceChar( pszPath, '//', '/' );
       }
 
       if ( strnicmp( pszPath, pszCgiRoot, strlen(pszCgiRoot) ) != 0 )
       {
              return MODULE_RUN_CONTINUE;
       }
 
       ret = CreatePipe( &hPipeRead, &hPipeWrite, &SecAttrib, 65536 );
 
       buf = MemAlloc( hr->hMem, 1024 );
       hProcess = cgi_exec( hPipeWrite, NULL, pszPath, NULL );
      
       while ( !bProcessDead )
       {
              int        dwRet;
 
              dwRet = WaitForSingleObject( hProcess, 1 );
              if ( dwRet != WAIT_TIMEOUT )
              {
                     bProcessDead = TRUE;
              }
 
              if (!PeekNamedPipe(hPipeRead, NULL, 0, NULL, &BytesInPipe, NULL))
              {
                     break;
              }
 
              if ( BytesInPipe != 0 )
              {
                     memset( buf, 0, sizeof(buf) );
                     dwRead = 0;
                     if ( ReadFile( hPipeRead, buf, 1024, &dwRead, NULL ) )
                     {
                            if ( dwRead > 0 )
                            {
                                   send( hr->s, buf, dwRead, 0 );
                            }
                     }
              }
       }
 
       do
       {
              if (!PeekNamedPipe(hPipeRead, NULL, 0, NULL, &BytesInPipe, NULL))
              {
                     break;
              }
 
              if ( BytesInPipe != 0 )
              {
                     memset( buf, 0, sizeof(buf) );
                     dwRead = 0;
                     if ( ReadFile( hPipeRead, buf, 1024, &dwRead, NULL ) )
                     {
                            if ( dwRead > 0 )
                            {
                                   send( hr->s, buf, dwRead, 0 );
                            }
                     }
              }
       } while ( BytesInPipe != 0);
 
       MemFree( hr->hMem, buf );
       CloseHandle( hProcess );
       CloseHandle( hPipeRead );
       CloseHandle( hPipeWrite );
 
    return MODULE_RUN_ENDSESSION;
}
 
在以上代码中,cgi_exec是实现创建进程,并将进程的输出定向到管道中,然后在cgi_writeclient()函数中,先创建管道,然后调用cgi_exec()函数创建cgi进程并将其输出定向到刚创建的管道中,         
然后调用WaitForSingleObject()函数来等待CGI进程运行,注意不是等到进程结束后才从管道读数据。
       在cgi进程的运行过程中,每等一段时间,就从管道中读取一部分数据,调用send()函数发送到socket中去。当等到cgi进程结束后,再从管道中将剩余的数据全部读出发送到socket中去。这样就实现了cgi的功能。

抱歉!评论已关闭.