谈谈在WebServer中如何实现CGI技术
2008-03-11 09:53
267 查看
谈谈在WebServer中如何实现CGI[b]技术[/b]
在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的功能。
在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的功能。
相关文章推荐
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 谈谈在WebServer中如何实现CGI技术
- 在WebServer中如何实现CGI技术
- DWR Server Push(服务器推技术) 实现即时聊天功能(WEB)
- WEB SERVER如何支持CGI/PHP/Perl ___ 程序的核心内容(2)