【问题标题】:Can multiple WT applications run on same port?多个 WT 应用程序可以在同一个端口上运行吗?
【发布时间】:2013-04-04 03:07:18
【问题描述】:

更新 1:我最近发现 WT 使用 TCP (HTTP) 进行通信,如果这对任何人都有帮助的话。

标题说明了一切,是否可以在同一个端口上运行 2 个不同的 WT 应用程序或项目?我知道 WT 已经通过它的启动参数来控制应用程序的托管方式,如下所示。我使用的是Visual Studio 2010,下面的参数在debugging->command arguments 框中输入如下:

--http-address=0.0.0.0 --http-port=8080 --deploy-path=/hello --docroot=.

以上参数将要求用户在以下位置打开网页

http://127.0.0.1:8080/hello

不过,如果我使用以下参数托管另一个项目会怎样?

--http-address=0.0.0.0 --http-port=8080 --deploy-path=/world --docroot=.

所以我需要连接到

http://127.0.0.1:8080/world

上面实际上是行不通的,它只托管第一个连接的应用程序,第二个应用程序直到第一个关闭后才会连接。所以这把我带到了这里。有没有其他方法可以在同一个端口上运行多个 WT 应用程序?

提前感谢您的帮助!

【问题讨论】:

    标签: c++ visual-studio-2010 port command-line-arguments wt


    【解决方案1】:

    是的,您可以做到这一点,但您需要创建自己的WRun 并使用addEntryPoint。这实际上是在tutorial 中提到的,具体如下:

    WRun() 内部

    WRun() 实际上是一个方便的函数,它创建和配置一个 WServer 实例。如果你想要更多的控制,例如如果你有多个“入口点”,或者想要控制服务器的启动和停止,你可以直接使用 WServer API。

    这里有一个示例,两个应用程序都是 Hello World 应用程序,但请注意它们在按钮上和按下它们时具有不同的标题和不同的消息。您可以在src/http/Serve.Csrc/Wt/WServer 上找到WRun 的另一个实现。

    two_helloworlds.cc

    #include <Wt/WApplication>
    #include <Wt/WBreak>
    #include <Wt/WContainerWidget>
    #include <Wt/WLineEdit>
    #include <Wt/WPushButton>
    #include <Wt/WText>
    #include <Wt/WException>
    #include <Wt/WLogger>
    #include <Wt/WServer>
    
    class HelloApplication : public Wt::WApplication
    {
    public:
        HelloApplication(const Wt::WEnvironment& env, const std::string& title);
    
    private:
        Wt::WLineEdit *nameEdit_;
        Wt::WText *greeting_;
    
        void greet();
    };
    
    HelloApplication::HelloApplication(const Wt::WEnvironment& env, const std::string& title)
        : Wt::WApplication(env)
    {
        setTitle(title);
    
        root()->addWidget(new Wt::WText("Your name, please ? "));
        nameEdit_ = new Wt::WLineEdit(root());
        Wt::WPushButton *button = new Wt::WPushButton("Greet me.", root());
        root()->addWidget(new Wt::WBreak());
        greeting_ = new Wt::WText(root());
        button->clicked().connect(this, &HelloApplication::greet);
    }
    
    void HelloApplication::greet()
    {    greeting_->setText("Hello there, " + nameEdit_->text());
    }
    class GoodbyeApplication : public Wt::WApplication{
    public:
        GoodbyeApplication(const Wt::WEnvironment& env, const std::string& title);
    
    private:    Wt::WLineEdit *nameEdit_;
        Wt::WText *greeting_;
    
    
        void greet();
    };
    
    GoodbyeApplication::GoodbyeApplication(const Wt::WEnvironment& env, const std::string& title)
        : Wt::WApplication(env)
    {
        setTitle(title);
    
        root()->addWidget(new Wt::WText("Your name, please ? "));
        nameEdit_ = new Wt::WLineEdit(root());
        Wt::WPushButton *button = new Wt::WPushButton("Say goodbye.", root());
        root()->addWidget(new Wt::WBreak());
        greeting_ = new Wt::WText(root());
        button->clicked().connect(this, &GoodbyeApplication::greet);
    }
    
    void GoodbyeApplication::greet()
    {
        greeting_->setText("Goodbye, " + nameEdit_->text());
    }
    
    Wt::WApplication *createApplication(const Wt::WEnvironment& env)
    {
        return new HelloApplication(env, "First app");
    }
    
    Wt::WApplication *createSecondApplication(const Wt::WEnvironment& env)
    {
        return new GoodbyeApplication(env, "Second app");
    }
    
    int YourWRun(int argc, char *argv[], Wt::ApplicationCreator createApplication, Wt::ApplicationCreator createSecondApplication)
    {
      try {
        // use argv[0] as the application name to match a suitable entry
        // in the Wt configuration file, and use the default configuration
        // file (which defaults to /etc/wt/wt_config.xml unless the environment
        // variable WT_CONFIG_XML is set)
        Wt::WServer server(argv[0],"");
    
        // WTHTTP_CONFIGURATION is e.g. "/etc/wt/wthttpd"
        server.setServerConfiguration(argc, argv, WTHTTP_CONFIGURATION);
    
        // add a single entry point, at the default location (as determined
        // by the server configuration's deploy-path)
        server.addEntryPoint(Wt::Application, createApplication);
        server.addEntryPoint(Wt::Application, createSecondApplication,"/second");
        if (server.start()) {
          int sig = Wt::WServer::waitForShutdown(argv[0]);
    
          std::cerr << "Shutdown (signal = " << sig << ")" << std::endl;
          server.stop();
    
          /*
          if (sig == SIGHUP)
            WServer::restart(argc, argv, environ);
          */
          }
      } catch (Wt::WServer::Exception& e) {
        std::cerr << e.what() << "\n";
        return 1;
      } catch (std::exception& e) {
        std::cerr << "exception: " << e.what() << "\n";
        return 1;
      }
    }
    
    int main(int argc, char **argv)
    {
        return YourWRun(argc, argv, &createApplication, &createSecondApplication);
    }
    

    用它编译

    g++ -g -o two_helloworlds two_helloworlds.cc -I/usr/local/include -L/usr/local/lib -lwthttp -lwt -lboost_random -lboost_regex -lboost_signals -lboost_system -lboost_thread -lboost_filesystem -lboost_program_options -lboost_date_time

    并执行

    ./two_helloworlds --docroot . --http-address 0.0.0.0 --http-port 8080

    localhost:8080 上,您将访问其中一个应用程序,在localhost:8080/second 上,您将访问另一个应用程序。

    【讨论】:

    • 好的,所以我玩弄了您发布的代码,这就是我想出的。如果在服务器启动之前创建入口点,则可以在同一端口上运行多个 WT 应用程序。最简单的方法是让两个 WT 应用程序位于同一个项目中,以便服务器可以创建入口点。如果在服务器启动之前没有创建入口点,则不可能在同一端口上运行多个 WT 应用程序,如果两个应用程序在两个不同的项目中完全分开,这是不可能的。你能确认这是正确的吗?
    • 另外,您发布的示例非常易于阅读和理解,您太棒了!
    • 没错,如果您将两个应用程序放在同一个项目中并在启动服务器之前设置它们的入口点,它应该会像魅力一样工作。
    猜你喜欢
    • 2013-04-26
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 2012-06-28
    • 1970-01-01
    • 2020-05-17
    • 2015-11-07
    相关资源
    最近更新 更多