一个应用程序中的 Non-Boost asio 错误,但另一个应用程序中没有

问题描述 投票:0回答:1

我有一个非常简单的 asio TCP 服务器:

using asio::ip::tcp;

class Client
{
public:
    Client(tcp::socket&& openedSocket)  : socket(std::move(openedSocket)), readBuffer(1024)
    {
        socket.async_read_some(asio::buffer(readBuffer.data(), readBuffer.size()), std::bind(&Client::handleRead, this, std::placeholders::_1, std::placeholders::_2));
    }

private:
    void handleRead(const asio::error_code& error, size_t numRead)
    {
        if(error)
        {
            std::cout << error.message() << std::endl;
        }
        else
        {
            std::cout << "Reading" << std::endl;
        }
    
        socket.async_read_some(asio::buffer(readBuffer.data(), readBuffer.size()), std::bind(&Client::handleRead, this, std::placeholders::_1, std::placeholders::_2));
    }

    tcp::socket socket;
    std::vector<uint8_t> readBuffer;
};

class Server
{
public:
    Server()  : acceptor(context, tcp::endpoint(tcp::v4(), 3030))
    {
        try
        {
            startAccept();
            context.run();
        }
        catch(const std::exception& e)
        {
            std::cout << e.what() << std::endl;
        }
    }

private:
    void startAccept()
    {
        acceptor.async_accept(std::bind(&Server::handleAccept, this, std::placeholders::_1, std::placeholders::_2));
    }

    void handleAccept(const asio::error_code& error, tcp::socket socket)
    {
        if(!error)
        {
            clients.push_back(std::make_unique<Client>(std::move(socket)));
        }
        else
        {
            std::cout << error.message() << std::endl;
        }
    
        startAccept();
    }

    asio::io_context context;
    tcp::acceptor acceptor;

    std::vector<std::unique_ptr<Client>> clients;
};

此代码适用于从基本主函数成功读取,该函数除了实例化服务器外什么都不做。

但是,当我在 JUCE 应用程序中运行此代码时,从 JUCE 消息线程实例化服务器,与客户端的连接成功但所有读取都会导致错误“文件描述符错误”。

为什么会这样?

c++ network-programming boost-asio
1个回答
0
投票

我们无法判断,因为我们没有看到代码。

我以前从未使用过 JUCE,但这是我的第一次使用,使用包含您的代码的基本 GUI 应用程序。我所做的唯一更改是允许服务器使用

thread_pool
作为上下文在后台运行。

#include <asio.hpp>
namespace SO {
using namespace std::placeholders;
using asio::ip::tcp;

class Client {
public:
  Client(tcp::socket &&openedSocket)
      : socket(std::move(openedSocket)), readBuffer(1024) {
    startRead();
  }

private:
  void startRead() {
    socket.async_read_some(asio::buffer(readBuffer),
                           bind(&Client::handleRead, this, _1, _2));
  }
  void handleRead(const asio::error_code &error, size_t numRead) {
    std::cout << "Reading (" << error.message() << ", " << numRead << ")"
              << std::endl;

    if (!error)
      startRead();
  }

  tcp::socket socket;
  std::vector<uint8_t> readBuffer;
};

class Server {
public:
  Server() : acceptor(context, tcp::endpoint(tcp::v4(), 3030)) {
    startAccept();
  }

  ~Server() {
    post(context, [this] {
      acceptor.cancel();
      acceptor.close();
    });
  }

private:
  void startAccept() {
    acceptor.async_accept(make_strand(context),
                          bind(&Server::handleAccept, this, _1, _2));
  }

  void handleAccept(const asio::error_code &error, tcp::socket socket) {
    if (!error) {
      clients.push_back(std::make_unique<Client>(std::move(socket)));
      startAccept();
    } else {
      std::cout << error.message() << std::endl;
    }
  }

  asio::thread_pool context;
  tcp::acceptor acceptor;

  std::vector<std::unique_ptr<Client>> clients;
};
} // namespace SO

//==============================================================================
class sehejuceApplication  : public juce::JUCEApplication
{
    std::shared_ptr<SO::Server> soTcpServer;
public:
    //==============================================================================
    sehejuceApplication() {}

    const juce::String getApplicationName() override       { return ProjectInfo::projectName; }
    const juce::String getApplicationVersion() override    { return ProjectInfo::versionString; }
    bool moreThanOneInstanceAllowed() override             { return true; }

    //==============================================================================
    void initialise (const juce::String& commandLine) override
    {
        // This method is where you should put your application's initialisation code..

        mainWindow.reset (new MainWindow (getApplicationName()));
        soTcpServer = std::make_shared<SO::Server>();
    }

    void shutdown() override
    {
        // Add your application's shutdown code here..

        mainWindow = nullptr; // (deletes our window)
        soTcpServer.reset();
    }

// rest unmodified as autogenerated by Projucer

现场演示:

© www.soinside.com 2019 - 2024. All rights reserved.