0

我一直在尝试使用 boost::asio 创建服务器和客户端,要求是服务器将提升客户端的进程。所以我实现了一个Master、一个Loader和一个Slave。

现在由于某种原因,它看起来并不是真正的多进程。IE服务器卡住并且没有收到来自客户端的任何答案,如果我让客户端在发送后异步等待答案,我得到的控制台打印是:

Slave Loaded
Slave::Resolved
Slave::Connected
Slave::Write Ended

IE主机没有收到从机的任何答案,顺便说一句,如果我删除客户端中的sync_read,我会得到:

Slave Loaded
Slave::Resolved
Slave::Connected
Slave::Write Ended
Slave Ended
Master::Received: 1

这让我更加认为这不是多进程......有人经历过吗?这些是文件(3个项目)大师:

#include <iostream>
#include <string>
#include <list>
#include <tchar.h>
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/bind.hpp>

using namespace std;
using namespace boost::asio;
using boost::asio::ip::tcp;
static int const s_srvCnt = 1;

class tcp_connection
  : public boost::enable_shared_from_this<tcp_connection>
{
public:
  typedef boost::shared_ptr<tcp_connection> pointer;

  static pointer create(boost::asio::io_service& io_service)
  {
    return pointer(new tcp_connection(io_service));
  }

  tcp::socket& socket()
  {
    return m_socket;
  }

  void start()
  {    
    async_read(m_socket, m_buf,
          boost::bind(&tcp_connection::received, this,
            boost::asio::placeholders::error));
  }

private:
  tcp_connection(boost::asio::io_service& io_service)
    : m_socket(io_service)
  {
  }

  void handle_write(const boost::system::error_code& /*error*/)
  {
  }

  void received(const boost::system::error_code& err) {
      cout << "Master::Received: " <<  &m_buf << endl;
      boost::asio::async_write(m_socket, boost::asio::buffer("Thanks"),
          boost::bind(&tcp_connection::handle_write, this,
            boost::asio::placeholders::error));

    }

  tcp::socket               m_socket;
  boost::asio::streambuf    m_buf;
};

class tcp_server
{
public:
  tcp_server(boost::asio::io_service& io_service)
    : m_acceptor(io_service, tcp::endpoint(tcp::v4(), 1300))
  {
    start_accept();
  }

private:
  void start_accept()
  {
    tcp_connection::pointer new_connection =
      tcp_connection::create(m_acceptor.get_io_service());

    m_acceptor.async_accept(new_connection->socket(),
        boost::bind(&tcp_server::handle_accept, this, new_connection,
          boost::asio::placeholders::error));
  }

  void handle_accept(tcp_connection::pointer new_connection,
      const boost::system::error_code& error)
  {
    m_connections.push_back(new_connection);
    if (!error)
    {
      new_connection->start();
    }

    start_accept();
  }

  tcp::acceptor m_acceptor;
  list<tcp_connection::pointer> m_connections;
};

void main()
{
    //list<wstring> processes; 
    //processes.push_back("Process1");
    //processes.push_back("Process2");
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    //LPWSTR concatted = concatted_stdstr.c_str();
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
    TCHAR params[100];
    // Start the child process. 
    boost::asio::io_service service;
    tcp_server server(service);
    size_t current = 0; 
    for (int i = 1 ; i <= s_srvCnt ; i++) {
        swprintf_s(params, TEXT("-id %d"), i);
        if( !CreateProcess(TEXT("D:\\Users\\myuser\\Documents\\Visual Studio 2012\\Projects\\MultiProcess\\x64\\Debug\\Loader.exe"),   // No module name (use command line) // change this to your local wherever you run from
            params,        // Command line //  -name Process1
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            0,              // No creation flags
            NULL,           // Use parent's environment block
            NULL,           // Use parent's starting directory 
            &si,            // Pointer to STARTUPINFO structure
            &pi )           // Pointer to PROCESS_INFORMATION structure
            )
        {
            printf( "CreateProcess failed (%d).\n", GetLastError() );
            return;
        }
        //current = service.poll_one();
    }
    //size_t polled = service.poll();
    service.run();
    cout << "Master Ended";
    //while(true);
}

奴隶:

#include "dllmain.h"
#include <iostream>
#include <tchar.h>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/bind.hpp>
using namespace std;

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

class client
{
public:
  client(boost::asio::io_service& io_service, const std::string& parms)
    : m_resolver(io_service),
      m_socket(io_service),
      m_params(parms)
  {

    // Start an asynchronous resolve to translate the server and service names
    // into a list of endpoints.
    tcp::resolver::query query("localhost", "1300");
    m_resolver.async_resolve(query,
        boost::bind(&client::handle_resolve, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::iterator));
  }

private:
  void handle_resolve(const boost::system::error_code& err,
      tcp::resolver::iterator endpoint_iterator)
  {
    if (!err)
    {
        cout << "Slave::Resolved" << endl;
      // Attempt a connection to each endpoint in the list until we
      // successfully establish a connection.
      boost::asio::async_connect(m_socket, endpoint_iterator,
          boost::bind(&client::handle_connect, this,
            boost::asio::placeholders::error));
    }
    else
    {
      std::cout << "Error1: " << err.message() << "\n";
    }
  }

  void handle_connect(const boost::system::error_code& err)
  {
    if (!err)
    {
        cout << "Slave::Connected" << endl;
      // The connection was successful. Send the request.
      boost::asio::async_write(m_socket, boost::asio::buffer(m_params),
          boost::bind(&client::handle_write, this,
            boost::asio::placeholders::error));
    }
    else
    {
      std::cout << "Error2: " << err.message() << "\n";
    }
  }

  void handle_write(const boost::system::error_code& err)
  {
    if (!err)
    {
      // Read the response status line. The response_ streambuf will
      // automatically grow to accommodate the entire line. The growth may be
      // limited by passing a maximum size to the streambuf constructor.
        cout << "Slave::Write Ended" << endl;
    /*  boost::asio::async_read(m_socket, m_buf,
          boost::bind(&client::handle_read, this,
            boost::asio::placeholders::error));*/

    }
    else
    {
      std::cout << "Error3: " << err.message() << "\n";
    }
  }
  void handle_read(const boost::system::error_code& err)
  {
    if (!err)
    {
      cout << "Slave::Received: " <<  &m_buf << endl;
    }
    else
    {
      std::cout << "Error4: " << err << "\n";
    }
  }

  tcp::resolver             m_resolver;
  tcp::socket               m_socket;
  boost::asio::streambuf    m_buf;
  std::string               m_params;
};
bool Init(int n, char* params[])
{
    std::string parameters;
    for (int i = 1 ; i < n ; ++i)
        parameters.append(params[i]);

    cout << "Slave Loaded" << endl;
    boost::asio::io_service service;
    client client(service, parameters);
    service.run();

    cout << "Slave Ended" << endl;
    return true;
}

从 h 文件:(dllmain.h)

#if !defined(__dllmain_h_Included_)
#define __dllmain_h_Included_

#if !defined(WIN32)
#   define SLAVE_API
#   if defined(SLAVE_EXPORTS)
#       define SLAVE_EXTERN
#   else
#       define SLAVE_EXTERN     extern
#   endif
#else
#   if defined(SLAVE_EXPORTS)
#       define SLAVE_API            __declspec(dllexport)
#       define SLAVE_EXTERN
#   else
#       define SLAVE_API            __declspec(dllimport)
#       define SLAVE_EXTERN     extern
#   endif
#endif

extern "C" SLAVE_API bool Init(int n, char* params[]);

#endif  // !defined(__dllmain_h_Included_)

装载机:

#include <iostream>
#include <string>
#include <windows.h>

using namespace std;

typedef bool (*Init)(int, char* params[]);

void main(int argc, char* argv[])
{
    HMODULE m_handle = ::LoadLibrary(TEXT("Slave.dll"));

    if (!m_handle) {
        cout
            << "failed loading dll: " << "" << " failed code " << GetLastError() << endl ;
    }
    void* foo = ::GetProcAddress(m_handle, "Init");

    Init f = (Init)foo;
    f(argc, argv);
    while(true) Sleep(10000);
}

帮助?


添加:


我现在确定这不是 boost 问题,而是进程创建问题。如果我使用任务管理器关闭第二个进程,那么主服务器会收到消息。所以我的问题是,为什么第二个进程会锁定创建它的第一个进程?

4

0 回答 0