Boost - 在服务器关闭套接字上为新客户端分叉

时间:2014-05-24 13:19:29

标签: c++ sockets boost boost-asio

嗨,我的帖子中有这段代码:

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....

所以基本上我想接受一个新的连接并制作一个分叉...孩子将向客户发送一些东西,父母将接受下一个连接......

但是当我在连接客户端后运行此代码时,它会在短时间内发送一些信息,然后它会停止发送信息...任何想法为什么?

由于

修改 过了一会儿,我试图发送一些数据:

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;
    }
}

正如您所指出的那样,问题在于发送数据,但我不知道为什么...... 之所以没有发送任何内容,是因为r->命令是空的,看起来它只包含fork之前的队列中的数据以及fork之后添加的所有内容都不在该队列中。

所以fork()可能会复制r指向的结构吗?它是“不再是指针”或它指向的位置被改变了吗?

谢谢

EDIT2: 因此,发送正在工作,但共享数据结构,如进程之间的指针不起作用。解决方案可以是boost inrerprocess,但我认为更好的方法是线程......

EDIT3:

我创建了一张图片,以便您更好地了解我想要做的事情:enter image description here

1。)客户端连接到终点 2.)服务器为每个客户端创建线程 3.)copy_thread将相同的日期复制到每个客户端专用队列 4.)clients_thread将数据发送到客户端

全局数据存储在r->命令指针中,数据是从多个方法“飞行”动态收集的...我想将相同的收集数据发送到所有客户端,直到我不会停止服务器线程 - 端点。 ..

希望你能理解我想要做的事情。感谢

2 个答案:

答案 0 :(得分:2)

作为参考,这是一个自包含的示例,只发送一个文件:

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

并且它可以正常工作:

#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;

        }
    }
}

使用netcat localhost 6767 | md5sum检查时,客户端每次都会收到文件的精确副本。

我认为你真正的问题不是分叉,而是发送。

答案 1 :(得分:0)

父进程返回,因此它将循环函数保留。在此之后,父母不接受下一个连接(因为它没有达到acceptor.accept();另一次)因此它不会向该客户端发送任何数据。