神秘的200连接从何而来?

发布于 2024-10-21 07:43:47 字数 2094 浏览 6 评论 0原文

嘿伙计们,我是异步编程的新手,这可能是一个愚蠢的问题,但它确实让我发疯了!

这是代码(它只是对 boost.asio 的示例进行了一些修改):

server.cpp:

class tcp_server
{
public:
    tcp_server(boost::asio::io_service& io_service)
        : acceptor_(io_service, tcp::endpoint(tcp::v4(), 10000)),limit(0)
    {
        start_accept();
    }

private:
    void start_accept()
    {
        while(1)
        {
            if(limit <= 10)
            {
                std::cout << limit << std::endl;
                break;
            }
        }

        tcp::socket* socket = new tcp::socket(acceptor_.io_service());

        acceptor_.async_accept(*socket,
            boost::bind(&tcp_server::handle_accept, this, boost::asio::placeholders::error));
    }

    void handle_accept(const boost::system::error_code& error)
    {
        if (!error)
        {
            ++limit ;
            start_accept();
        }
    }

    tcp::acceptor acceptor_;

    int limit;
};

int main()
{
    try
    {
        boost::asio::io_service io_service;
        tcp_server server(io_service);
        io_service.run();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

client.cpp:

int main(int argc, char* argv[])
{
    int i = 0;

    while(1)
    {
        try
        {
            boost::asio::io_service io_service;

            tcp::resolver resolver(io_service);
            tcp::resolver::query query("127.0.0.1", "10000");
            tcp::resolver::iterator endpoint_iterator =resolver.resolve(query);
            tcp::endpoint endpoint = *endpoint_iterator;

            tcp::socket socket(io_service);
            socket.close();
            socket.connect(endpoint);

            std::cout << i++ << std::endl;
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
    }

    return 0;
}

我只是想限制服务器接受 10 个客户端。 然而,客户端在计算出“惊人”的210(不多也不少)个连续数字后,就抛出了错误信息。 发生了什么事??

Hey guys, i'm a newbie to async-programming, this is probably a stupid question, but it indeed drove me crazy!!

Here's the code (it just modified a bit from boost.asio's sample):

server.cpp:

class tcp_server
{
public:
    tcp_server(boost::asio::io_service& io_service)
        : acceptor_(io_service, tcp::endpoint(tcp::v4(), 10000)),limit(0)
    {
        start_accept();
    }

private:
    void start_accept()
    {
        while(1)
        {
            if(limit <= 10)
            {
                std::cout << limit << std::endl;
                break;
            }
        }

        tcp::socket* socket = new tcp::socket(acceptor_.io_service());

        acceptor_.async_accept(*socket,
            boost::bind(&tcp_server::handle_accept, this, boost::asio::placeholders::error));
    }

    void handle_accept(const boost::system::error_code& error)
    {
        if (!error)
        {
            ++limit ;
            start_accept();
        }
    }

    tcp::acceptor acceptor_;

    int limit;
};

int main()
{
    try
    {
        boost::asio::io_service io_service;
        tcp_server server(io_service);
        io_service.run();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

client.cpp:

int main(int argc, char* argv[])
{
    int i = 0;

    while(1)
    {
        try
        {
            boost::asio::io_service io_service;

            tcp::resolver resolver(io_service);
            tcp::resolver::query query("127.0.0.1", "10000");
            tcp::resolver::iterator endpoint_iterator =resolver.resolve(query);
            tcp::endpoint endpoint = *endpoint_iterator;

            tcp::socket socket(io_service);
            socket.close();
            socket.connect(endpoint);

            std::cout << i++ << std::endl;
        }
        catch (std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
    }

    return 0;
}

I just wanna limit server to accept 10 client.
However, client cout the error information after it cout "amazing" 210 (never more or less) continuous numbers.
What happend??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清风疏影 2024-10-28 07:43:47

我对 server.cpp 做了一些更改。首先在构造函数上重新配置acceptor_。删除了 while 循环,添加了acceptor_.close();

#include <boost/asio/io_service.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

using namespace boost::asio;
using namespace boost::asio::ip;

class tcp_server
{
public:
    tcp_server(boost::asio::io_service& io_service)
        : acceptor_(io_service),limit(0)
    {
        tcp::endpoint endpoint(tcp::v4(), 10000);
        acceptor_.open(endpoint.protocol());
        acceptor_.bind(endpoint);
        acceptor_.listen(1); //accept 1 connection at a time
        start_accept();
    }

private:
    void start_accept()
    {
        tcp::socket* socket = new tcp::socket(acceptor_.io_service());
        acceptor_.async_accept(*socket,
            boost::bind(
                &tcp_server::handle_accept,
                this,
                socket,
                boost::asio::placeholders::error));
    }

    void handle_accept(tcp::socket* s, const boost::system::error_code& error)
    {
        if (!error)
        {
            ++limit;
            if (limit < 9)
            {
                start_accept();
            }
            else
            {
                acceptor_.close();
            }           

        }
    }

    tcp::acceptor acceptor_;

    int limit;
};

int main()
{
    try
    {
        boost::asio::io_service io_service;
        tcp_server server(io_service);
        io_service.run();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

我想,默认接受器可以一次 async_accept 200 个连接事件。您可以在无限循环中从客户端打开一个套接字并关闭它。结果你打开和关闭一个连接 200 次,但它仍然是 1 个连接,1 个套接字。

通过调用listen(1)将其上限设置为1,将强制接受者触发事件。您增加计数,然后客户端关闭连接。这样您就可以正确计算每个连接事件。

最后说明: 异步 io 使用 1 个线程来处理连接事件、检索数据等...因此,不需要使用互斥体。

I've changed server.cpp a bit. First reconfigured acceptor_ on constructor. Removed while loop, added acceptor_.close();

#include <boost/asio/io_service.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

using namespace boost::asio;
using namespace boost::asio::ip;

class tcp_server
{
public:
    tcp_server(boost::asio::io_service& io_service)
        : acceptor_(io_service),limit(0)
    {
        tcp::endpoint endpoint(tcp::v4(), 10000);
        acceptor_.open(endpoint.protocol());
        acceptor_.bind(endpoint);
        acceptor_.listen(1); //accept 1 connection at a time
        start_accept();
    }

private:
    void start_accept()
    {
        tcp::socket* socket = new tcp::socket(acceptor_.io_service());
        acceptor_.async_accept(*socket,
            boost::bind(
                &tcp_server::handle_accept,
                this,
                socket,
                boost::asio::placeholders::error));
    }

    void handle_accept(tcp::socket* s, const boost::system::error_code& error)
    {
        if (!error)
        {
            ++limit;
            if (limit < 9)
            {
                start_accept();
            }
            else
            {
                acceptor_.close();
            }           

        }
    }

    tcp::acceptor acceptor_;

    int limit;
};

int main()
{
    try
    {
        boost::asio::io_service io_service;
        tcp_server server(io_service);
        io_service.run();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

I suppose, default acceptor can async_accept 200 connection events at a time. You open a socket and close it from the client side in an infinite loop. As a result you open and close a connection 200 times, but it is still 1 connection, 1 socket.

Capping it to 1 by calling listen(1), would force the acceptor to fire an event. You increase the count, then client closes the connection. This way you correctly count each connection event.

Last note: async io uses 1 thread to process connection events, retrieved data etc... Thus, use of mutexes are not necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文