我正在寫一個簡單的ProxyServer來分析包並將它們發送到另一個服務器實例,例如,是這樣的:Boost :: Asio:async_read問題
客戶端 - > 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。
任何想法可能是什麼問題?
舊的代碼做了這樣的事情: 與接受方法調用的主要方法創建兩個線程
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不踩踏或我在做一些可怕的錯誤在這裏:-)?
我發佈的代碼爲小訪問代理服務器的位置:
session.h:link
session.cpp:link
server.h:link
server.cpp:link
ProxyServer.cpp:link
session :: data_是什麼類型? – 2011-06-04 01:27:11
你爲什麼要用ASIO混合和匹配'recv()'和'send()'調用?我認爲你需要改變你對recv(2)的錯誤處理,以便它檢查成功,然後假設失敗,並假設唯一的返回碼是'SOCKET_ERROR'。 – Sean 2011-06-04 02:05:39
@Sean我不認爲@user正在混合它們,使用'send'和'recv'的代碼是一些舊的winsock代碼。 – 2011-06-04 14:47:15