c++ - boost asio 服务器在关闭 boost::socket 的调用中挂起

标签 c++ sockets boost boost-asio

下面是我使用 boost asio 的套接字服务器示例代码。

此服务器将在端口 10001 上等待任何客户端连接。当任何客户端连接时,它将启动线程以从该客户端读取并等待另一个客户端。但是,当我的客户端断开连接时,服务器套接字卡在 my_socket->close() 调用中会发生什么。

如果新客户端尝试连接服务器崩溃。

我正在使用 g++ (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3

#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <sys/socket.h>
#include <unistd.h>
#include <string>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>

using namespace std;
using boost::asio::ip::tcp;

void run(boost::shared_ptr<tcp::socket> my_socket)
{
    while (1)
    {
        char buf[128];
        boost::system::error_code error;

        size_t len = my_socket->read_some(boost::asio::buffer(buf, 128), error);
        std::cout << "len : " << len << std::endl;

        if (error == boost::asio::error::eof)
        {
            cout << "\t(boost::asio::error::eof)" << endl;
            if (my_socket->is_open())
            {
                boost::system::error_code ec;
                cout << "\tSocket closing" << endl;
                my_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
                cout << "\tShutdown " << ec.message() << endl;
//                cout << "normal close : " << ::close(my_socket->native_handle()) << endl;
                my_socket->close(ec);
                cout << "\tSocket closed" << endl;
            }
            break; // Connection closed cleanly by peer.
        }
        else if (error)
        {
            std::cout << "Exception : " << error.message() << std::endl;
            break;
        }
        else
        {
            for (unsigned int i = 0; i < len; i++)
                printf("%02x ", buf[i] & 0xFF);
            printf("\n");
        }
    }
}

int main()
{
    const int S = 1000;
    vector<boost::shared_ptr<boost::thread> > arr_thr(S);

    try
    {
        for (uint32_t i = 0;; i++)
        {
            boost::asio::io_service io_service;

            tcp::endpoint endpoint(tcp::v6(), 10001);

            boost::shared_ptr<tcp::socket> my_socket(new tcp::socket(io_service));
            tcp::endpoint end_type;

            tcp::acceptor acceptor(io_service, endpoint);

            std::cout << "before accept" << endl;
            acceptor.accept(*my_socket, end_type);

            std::cout << "connected... hdl : " << my_socket->native_handle() << std::endl;

            boost::asio::ip::address addr = end_type.address();
            std::string sClientIp = addr.to_string();

            std::cout << "\tclient IP : " << sClientIp << std::endl;
            arr_thr[i] = boost::shared_ptr<boost::thread>(new boost::thread(&run, my_socket));
        }
    } catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

最佳答案

启动run线程后,main中的for循环再次开始,销毁并重新初始化本地io_service变量,套接字上的下一个事件仍会假设旧的 io_service 对象,导致你的崩溃。

您应该只使用一个 io_service 实例。

另外,你应该看看 boost::asio 提供的异步函数,比如 async_acceptasync_read,例如这个例子:http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio/example/chat/chat_server.cpp

关于c++ - boost asio 服务器在关闭 boost::socket 的调用中挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14273816/

相关文章:

c++ - 哈希输出为 BYTE 而不是 std::string?

c++ - boost::asio 检查器

Java 套接字 : Client 'calling an object' on the server?(与 C# WCF 类似)

c++ - io_context : linking error for the latest boost library 的 undefined symbol

c++ - 在C++中不使用平方根函数计算平方根

c++ - 如何重置 VisualStudio(VS2010、VS2012)调试器缓存?

c++ - 可变大小的对象可能未被初始化

c# - NetworkStream Read 在死亡之前会等待多长时间?

c++ - 我怎样才能从 boost::random 得到 lognormal_distribution 来像 boost::math::lognormal_distribution

c++ - 用 boost::shared_ptr<std::list<T>> 初始化 boost::shared_ptr<std::vector<T>>