我正在尝试了解特定的网络架构。 有一个以这种方式工作的 cgi web 应用程序。
来自 Web 浏览器的请求到达 Apache Web 服务器,然后路由到应用程序调度程序。
应用程序调度程序有一个配置文件,其中包含所有可能的命令及其相应的处理程序方法。
比如说,如果浏览器有一个 cmd=_login
请求,调度程序会查找可能包含此条目的配置文件。
Command: _login
Handler: handle_login()
Header: login.h
Binary: Exe_name
那么,application dispatcher可以通过哪些方式fork出cgi二进制文件(Exe_name),直接调用handle_login()
函数呢?
是否可以直接调用特定方法?
最佳答案
基本上有两种方法来进行符号解析。
内置符号解析。
根据您的系统,您可以在运行时使用的隐藏符号表中按名称查找常规函数。例如, dlopen()
和 dlsym()
在类 UNIX 系统上允许您加载共享对象库并按名称解析该库中的函数。 Windows 具有类似的行为功能 LoadLibrary()
和 GetProcAddress()
用于动态链接库 (DLL)。您必须注意可见性 的概念。函数必须由库导出才能使用此机制解析。我相信 GCC 默认创建导出所有函数(可见性是公开的),而 Windows 编译器默认不导出任何内容。另请注意,在 Windows 上,您可以在不加载外部库的情况下解析主机程序中的函数,因为空库句柄指定了主机进程的可执行镜像。
总的来说,这充满了微妙之处并且不可移植。我不建议你基于这种机制构建系统。
手动符号解析:路线
将 URL(或 URL 的一部分)映射到函数的现代方法是构建 URL 路由。这种方法被大多数基于 MVC 范例的现代 Web 框架所采用(Ruby on Rails、Django 和 ASP.NET MVC 仅举几例——还有许多其他范例)。
这基本上包括构建名称(或正则表达式)到回调的映射(在 C++ 中,这将是指向函数或 std::function<>
对象的指针)。如果您的编译器支持即将到来的标准,您应该能够填充 std::map< std::regex,std::function<void()>>
对象来实现查找。
这是一个简单的(未经测试的)示例:
// GET request for login.
void handle_login_page ()
{
// CGI handler: read from `std::cin` and write to `std::cout`...
}
// POST request for login.
void handle_login_form ()
{
// CGI handler: read from `std::cin` and write to `std::cout`...
}
typedef std::function<void()> Handler;
typedef std::map<std::string, Handler> Routes;
void handle_request ( const Routes& routes, const std::string& command )
{
// locate handler.
Routes::const_iterator match = routes.find(command);
if (match == routes.end()) {
// exit with 404 status.
}
const Handler handler = match->second;
// log access or other pre-processing.
// ...
// invoke handler.
handler();
}
int main ()
{
Routes routes;
routes["get_login"] = &handle_login_page;
routes["post_login"] = &handle_login_form;
// ...
// accept a connection.
// fork.
// get command name.
const std::string command = ...;
handle_request(routes, command);
}
关于c++ - C++中处理函数的动态调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8692061/