您的位置:首页 > 其它

谈谈在WebServer中如何实现CGI技术

2008-01-03 09:26 651 查看
[align=center]谈谈WebServer中如何实现CGI[b]技术[/b][/align][align=center] [/align]在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的功能。  

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=888964
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: