我正在编写一个简单的ProxyServer来分析包并将它们发送到另一个服务器实例,例如像这样的东西:
客户 - > MyProxy - > SQLServer - >
客户端< - MyProxy< - SQLServer< -
它应该在无限循环中运行。 我现在的问题是代理似乎松散了包,有时甚至挂起。 当我添加大量调试信息(写入控制台)时,ProxyServer就是 更加稳定。似乎ProxyServer太快..: - )
我很确定我做错了什么,这是我的会话类的代码(代码来自Boost :: Asio示例)。
#include "session.h"
#include <iostream>
using namespace std;
session::session(boost::asio::io_service& io_service)
: socket_(io_service)
, sqlsocket_(io_service)
, io_service_(io_service)
, resolver(io_service)
{
cout << "session::session()" << endl;
}
session::~session()
{
cout << "session::~session()" << endl;
cout << "closing session ..." << endl;
}
tcp::socket& session::socket()
{
return socket_;
}
void session::start()
{
cout << "session::start()" << endl;
cout << "starting session ..." << endl;
// connect to the sqlserver database
tcp::resolver::query query("192.168.1.50", "1317");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::endpoint endpoint = *endpoint_iterator;
sqlsocket_.async_connect(endpoint,
boost::bind(&session::handle_sqlserver_connect, this,
boost::asio::placeholders::error, ++endpoint_iterator));
// TODO: connect to the connector
}
void session::handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
cout << "session::handle_read()" << endl;
if (!error)
{
cout << "session::handle_read() (read: "
<< bytes_transferred << ")"
<< endl;
boost::asio::async_write(sqlsocket_,
boost::asio::buffer(data_, bytes_transferred),
boost::bind(&session::handle_sqlserver_write, this,
boost::asio::placeholders::error, bytes_transferred));
}
else
{
delete this;
}
}
void session::handle_sqlserver_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
cout << "session::handle_sqlserver_read()" << endl;
if (!error)
{
cout << "session::handle_sqlserver_read() (read: "
<< bytes_transferred << ")"
<< endl;
boost::asio::async_write(socket_,
boost::asio::buffer(data_, bytes_transferred),
boost::bind(&session::handle_write, this,
boost::asio::placeholders::error, bytes_transferred));
}
else
{
delete this;
}
}
void session::handle_write(const boost::system::error_code& error,
size_t bytes_transferred)
{
static int count = 0;
cout << ++count << ". session::handle_write()" << endl;
if (!error)
{
cout << "session::handle_write() (read: "
<< bytes_transferred << ")"
<< endl;
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
delete this;
}
}
void session::handle_sqlserver_write(const boost::system::error_code& error,
size_t bytes_transferred)
{
cout << "session::handle_sqlserver_write()" << endl;
if (!error)
{
cout << "session::handle_sqlserver_write() (read: "
<< bytes_transferred << ")"
<< endl;
sqlsocket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_sqlserver_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
delete this;
}
}
void session::handle_sqlserver_connect(const boost::system::error_code& error,
tcp::resolver::iterator endpoint_iterator)
{
cout << "session::handle_sqlserver_connect()" << endl;
if (!error)
{
socket_.async_read_some(boost::asio::buffer(data_, max_length),
boost::bind(&session::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else if (endpoint_iterator != tcp::resolver::iterator())
{
sqlsocket_.close();
tcp::endpoint endpoint = *endpoint_iterator;
sqlsocket_.async_connect(endpoint,
boost::bind(&session::handle_sqlserver_connect, this,
boost::asio::placeholders::error, ++endpoint_iterator));
}
}
我的代理类型是否需要使用其他方法而不是async_ *? 我正在从我的公司想要重新启动的一些旧项目移植代码,但使用boost而不是之前使用的Winsock内容。
知道可能是什么问题吗?
旧代码做了这样的事情: 使用accept方法调用的main方法创建了两个线程
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)listenatclient, (LPVOID)cs, 0, 0);
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)listenatserver, (LPVOID)cs, 0, 0);
并且线程调用以下函数:
void listenatclient(LPVOID connection)
{
connection_s* cs = (connection_s*)connection;
char inMessagecli[MSG_SIZE];
int rcount = 0;
...
do
{
memset(inMessagecli, 0, MSG_SIZE);
rcount = recv((SOCKET)cs->client, inMessagecli, MSG_SIZE, 0);
if (rcount != SOCKET_ERROR)
{
// analyze package
...
send((SOCKET)cs->server, inMessagecli, rcount, 0);
}
} while (rcount > 0);
}
void listenatserver(LPVOID connection)
{
connection_s* cs = (connection_s*)connection;
char inMessageserv[MSG_SIZE];
int rcount = 0;
do
{
memset(inMessageserv, 0, MSG_SIZE);
rcount = recv((SOCKET)cs->server, inMessageserv, MSG_SIZE, 0);
if (rcount != SOCKET_ERROR)
{
send((SOCKET)cs->client, inMessageserv, rcount, 0);
}
} while (rcount > 0);
}
[编辑]: 我试图同时为客户端和sqlserver运行async_read命令,但现在我总是崩溃,有时在boost :: bind中,有时在boost库的其他部分。
似乎发生的是创建了2个或3个连接(3个会话)。在关闭第一个会话时,崩溃似乎发生在第二个会话中。
提升asio是不是没有踏板,或者我在这里做了一些非常错误的事情:-)?
我在这里发布了小型ProxyServer的代码:
session.h:link
session.cpp:link
server.h:link
server.cpp:link
ProxyServer.cpp:link
答案 0 :(得分:4)
我怀疑发生的事情是你的一个async_read_some调用正在返回“某些”数据,但还不足以让SQL服务器满意它收到了一个完整的请求。您的代码始终遵循read_from_client - &gt;的路径。 send_to_server - &gt; read_from_server - &gt; send_to_client。它不处理你需要read_from_client - &gt;的情况。 send_to_server - &gt; read_from_client - &gt; send_to_server - &gt; read_from_server - &gt; send_to_client。
到目前为止您编写的代码与原始代码的执行操作不同。具体来说,旧代码同时监听两个套接字上的读取。幸运的是,由于您使用的是ASIO,因此您不需要乱用线程。只需在两个套接字上同时发出async_read_some请求,并异步处理它们。