私はboost::asioを使用してサーバーとクライアントを作成しようとしていますが、サーバーがクライアントのプロセスを起動することが要件です。そのため、マスター、ローダー、スレーブを実装しました。
何らかの理由で、実際にはマルチプロセスではないように見えます。IE サーバーがスタックしており、クライアントからの応答を受信していません。送信後にクライアントが非同期的に応答を待機するようにすると、コンソールの出力は次のようになります。
Slave Loaded
Slave::Resolved
Slave::Connected
Slave::Write Ended
つまり、マスターがスレーブからの応答を受信していません。ところで、クライアントで 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);
}
ヘルプ?
添加:
ブーストの問題ではなく、プロセス作成の問題であると確信しています。タスクマネージャーを使用して2番目のプロセスを閉じると、マスターはメッセージを受け取ります。私の質問は、なぜ2番目のプロセスがそれを作成した1番目のプロセスをロックするのですか?