简体   繁体   中英

Boost - fork for new client on server closing socket

Hi I have this code in my thread:

boost::asio::io_service io_service;


tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), serverPort));

r->serverRunning = true;
tcp::socket socket_(io_service);
io_service.run();

while(1)
{
    if(boost::this_thread::interruption_requested())
    {
        acceptor.close();                    

    }
    acceptor.accept(socket_);

    io_service.notify_fork(boost::asio::io_service::fork_prepare);

    if (fork() == 0)
    {
        io_service.notify_fork(boost::asio::io_service::fork_child);
        acceptor.close();

        break;

    }
    else
    {
        io_service.notify_fork(boost::asio::io_service::fork_parent);
        socket_.close();
        continue;

    }
}
sent something to client....

so basically I want to accept a new conection and make a fork... child will be sending something to client and parent will accept next connection...

But when I run this code after connecting a client it will be sending some information just for a short time and then it will stop sending informations... any ideas why?

Thanks

EDIT: After the while I`m trying to send some data:

boost::asio::streambuf b;
std::ostream os(&b);
boost::system::error_code error;


for (;;)
{
    try
    {
        std::string message = "";
        bool empty = false;

        r->command_mutex.lock();
            empty = r->commands->empty();
        if(!empty){
            Command c;

            c = r->commands->front();
            r->commands->pop();

            os << c;

            size_t n = boost::asio::write(socket_, b, error);
            b.consume(n);    
        }
        r->command_mutex.unlock();

        boost::this_thread::interruption_point();

    }
    catch(boost::thread_interrupted&)
    {
        std::cout << "Thread is stopped" << std::endl;

        return;
    }
}

As you pointed the problem is with the sending data, but I do not know why... The reason why it is not sending anything is because r->commands is empty, well it looks that it contains just data which were in the queue before fork and everything what is added after fork is not in that queue..

so it is possible that fork() will copy the structure on which r points? that it is "not a pointer anymore" or that location on which it pointed is changed?

Thanks

EDIT2: So, sending is working but sharing data structures like pointers between processes is not working. Solution can be boost inrerprocess but I think better way is threads...

EDIT3:

I created a picture so you can better understand what I want to do: 在此输入图像描述

1.) clients connect to the end point 2.) server for each client create thread 3.) copy_thread copies same date to each client private queue 4.) clients_thread sending data to the clients

Global data are stored in r->commands pointer, data are gathered dynamically on "fly" from multiple methods... I want to send same gathered data to all clients until I will not stop the server thread - endpoint...

Hope that you will understand what I am trying to do. Thanks

For reference, here is a self contained example that just sends a large file:

std::ifstream ifs("/etc/dictionaries-common/words");
std::string cpp(std::istreambuf_iterator<char>(ifs), {});
socket_.write_some(boost::asio::buffer(cpp));

and it works correctly:

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <fstream>

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

struct R { 
    bool serverRunning = false;
};

int main()
{
    auto serverPort = 6767;

    boost::asio::io_service io_service;

    auto r = std::unique_ptr<R>(new R);

    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), serverPort));

    r->serverRunning = true;
    tcp::socket socket_(io_service);
    io_service.run();

    while(1)
    {
        if(boost::this_thread::interruption_requested())
        {
            acceptor.close();                    

        }
        acceptor.accept(socket_);

        io_service.notify_fork(boost::asio::io_service::fork_prepare);

        if (fork() == 0)
        {
            io_service.notify_fork(boost::asio::io_service::fork_child);
            acceptor.close();

            std::ifstream ifs("/etc/dictionaries-common/words");
            std::string cpp(std::istreambuf_iterator<char>(ifs), {});
            socket_.write_some(boost::asio::buffer(cpp));
            break;
        }
        else
        {
            io_service.notify_fork(boost::asio::io_service::fork_parent);
            socket_.close();
            continue;

        }
    }
}

When checked with netcat localhost 6767 | md5sum netcat localhost 6767 | md5sum , the client receives exact copies of the file each time.

I think your real problem isn't the forking, but the sending.

The parent returns, so it leaves the function with the loop. After this, the parent doesn't accept the next connection (because it doesn't reach acceptor.accept(); another time) so it doesn't send any data to the this client.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM