0

I am having a C++ server listening to PHP clients. The client code is the following:

<?php
    function connect_($message)
    {
        $port = 13;
        $address = "127.0.0.1";//talk to localhost
        $response = "";

        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket !== false)
        {
            $result = socket_connect($socket, $address, $port);
            if ($result !== false)
            {
                socket_write($socket, $message, strlen($message));//send the message
                while ($out = socket_read($socket, 2048)) $response .= $out;//get the response
                socket_close($socket);//exit
            }
        }

        return $response;
    }

    echo connect_('hi');
?>

This code is called every time a user visits the site.

The c++ server's code is the following (from here: https://stackoverflow.com/a/26577384/4143251):

#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
#include <boost/thread.hpp>

using boost::asio::ip::tcp;

char complex_function()
{
    //sleep to simulate a time consuming function
    boost::this_thread::sleep(boost::posix_time::milliseconds(10000));

    return 'C';//return the result of the work
}

class session : public std::enable_shared_from_this<session> {
  public:
    session(tcp::socket socket) : socket_(std::move(socket)) {}

    void start() { do_read(); }

    ~session()
    {
        std::cout << "USER GONE\n";
    }

  private:
    void do_read() {
        auto self(shared_from_this());
        socket_.async_read_some(boost::asio::buffer(data_, max_length),
                                [this, self](boost::system::error_code ec, std::size_t length) {
            if (!ec) {
                data_[0] = complex_function();
                length = 1;
                do_write(length);//good, now go write the response
            }
        });
    }

    void do_write(std::size_t length) {
        auto self(shared_from_this());
        boost::asio::async_write(socket_, boost::asio::buffer(data_, length),
                                 [this, self](boost::system::error_code ec, std::size_t /*length*/) {
            if (!ec) {
                //do, nothing here
            }
        });
    }

    tcp::socket socket_;
    enum { max_length = 1024 };
    char data_[max_length];
};

class server {
  public:
    server(boost::asio::io_service &io_service, short port)
            : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), socket_(io_service) {
        do_accept();
    }

  private:
    void do_accept() {
        acceptor_.async_accept(socket_, [this](boost::system::error_code ec) {
            if (!ec) {
                std::cout << "NEW USER\n";
                std::make_shared<session>(std::move(socket_))->start();
            }

            do_accept();
        });
    }

    tcp::acceptor acceptor_;
    tcp::socket socket_;
};

int main() {
    try {
        std::string port = "13";
        boost::asio::io_service io_service;

        server s(io_service, std::atoi(port.c_str()));

        boost::thread_group tg;
        for (int i=0; i < 10; ++i)//handle up to 10 clients at the same time
            tg.create_thread([&]{ io_service.run(); });

        tg.join_all();
    }
    catch (std::exception &e) {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}

Now, if I open in multiple tabs the PHP webpage and try to connect to the server from 5 clients at the same time, the server process the requests with 10 seconds delay.

The question is: how to make the above code process multiple requests at the same time in parallel?

Community
  • 1
  • 1
SpeedCoder
  • 139
  • 10
  • Asynchronous doesn't mean it's run on several threads. If you run a sleep function, it's blocking the entire thread. You need to have a new thread for each connection. Or you can use Boost's [timers](http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/tutorial/tuttimer2.html) to have similar features in an asynchronous environment. – Florian Margaine Oct 27 '14 at 14:04
  • @Florian Margaine: Thanks, so it seems like C++ is to blame? – SpeedCoder Oct 27 '14 at 14:06
  • @SpeedCoder ... or just asio – Barry Oct 27 '14 at 14:19
  • neither asio or c++ is to blame.I think ASIO io_service is not used correctly. Can you check again http://www.boost.org/doc/libs/1_48_0/doc/html/boost_asio/example/echo/async_tcp_echo_server.cpp impl – Arunmu Oct 27 '14 at 14:40
  • @Arunmu: My code is based on the 2011 Async TCP example, not sure what I am doing wrong... – SpeedCoder Oct 27 '14 at 14:43
  • Tested on my machine the request are processed in parallel, there is an overall delay of 10 seconds, but if i launch multiple requests at the same time, they respond approximately at the same time. If your server has only one core available, it might explain your result. – Drax Oct 27 '14 at 15:18
  • @Drax: This is not the behavior I see on my machine. I am using XAMPP on 64 bit windows 7. Is XAMPP known to use only 1 core? – SpeedCoder Oct 27 '14 at 16:45
  • @SpeedCoder Don't know, it's worth noting i've only tested the server part and launched the clients manually with telnets. – Drax Oct 27 '14 at 16:48
  • @Drax: If possible, can you try opening multiple tabs in chrome? – SpeedCoder Oct 27 '14 at 16:51
  • @Drax: Thanks, it seems my PHP installation is not multithreaded. I am going to look into this. – SpeedCoder Oct 27 '14 at 17:08
  • @SpeedCoder I already answered this in the other answer. Specifically: "_as a **poor-man's solution** add more threads (this simply means that if more requests arrive at the same time than there are threads to handle them, it **will still block until the first thread becomes available** to pick up the new request)_". So, choose the `deadline_timer` solution already. – sehe Oct 28 '14 at 22:19
  • 1
    It's quite painful to see how much more time was wasted here. I'll tell you this: C++ is not to blame. – sehe Oct 28 '14 at 22:20

0 Answers0