请对socket编程有丰富经验的朋友进来看一个boost.asio通信的问题

facat 2011-08-11 03:35:50
我用boost.asio库写了一个server和一个client。功能很简单,client把输入的字符发送出去,server就接收下来显示出来。我现在遇到一个很奇怪的问题,就是偶尔在server端会出现995错误。995错误的意思是
“由于线程退出或应用程序请求,已中止i/o操作”

由于是偶尔出现,所以我很难差到原因。而且是一连接收几十次不出错,然后下一次就突然出错。或者接连几次出错,然后又几十次不出错。

请大家帮我看看是不是有什么地方应该处理的我没处理。

附代码在下面,不过我估计不会有人看的,只希望大家根据自己的经验提出一些可能出现995错误的原因。

公用类:

#ifndef __TCP_ECHO_CONNECTION
#define __TCP_ECHO_CONNECTION

#include <boost/asio.hpp>

class tcp_echo_connection
{
public:
tcp_echo_connection(boost::asio::io_service& _io_srvice);

//tcp_echo_connection(){};
boost::asio::ip::tcp::socket& getsocket();
tcp_echo_connection* getthis()
{
return this;
}
private:
boost::asio::ip::tcp::socket _socket;
};

tcp_echo_connection::tcp_echo_connection(boost::asio::io_service& _io_srvice) :
_socket(_io_srvice)
{

}

boost::asio::ip::tcp::socket& tcp_echo_connection::getsocket()
{
return _socket;
}


#endif




server:

#define _WIN32_WINNT 0x0600
#define _GLIBCXX_DEBUG
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING

#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <list>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/bind.hpp>
#include "tcp_echo_connection.h"
using namespace std;
class tcp_echo_connection;
class tcp_echo_server;

class tcp_echo_server
{
public:
tcp_echo_server(boost::asio::io_service& _io_srvice,
boost::asio::ip::tcp::endpoint &_endpoint);
private:
void start_acceptor(boost::asio::io_service& _io_srvice);
void action(boost::shared_ptr<tcp_echo_connection> tcp_conn,
const boost::system::error_code& error);
void asy_read();
void asy_read_handle(boost::shared_array<char> revdata,
const boost::system::error_code& error, // Result of operation.
std::size_t bytes_transferred // Number of bytes read.
);
private:
boost::asio::ip::tcp::acceptor _acceptor;
const static int MAX_ACCEPTOR = 5;
static int acceptor_count;

};

int tcp_echo_server::acceptor_count = 0;

void tcp_echo_server::start_acceptor(boost::asio::io_service& _io_srvice)
{
acceptor_count++;
boost::shared_ptr<tcp_echo_connection> ptr(
new tcp_echo_connection(_io_srvice));
cout << "start accepting" << endl;
cout << "current accepting count: " << acceptor_count << endl;
_acceptor.async_accept(
ptr->getsocket(),
boost::bind(&tcp_echo_server::action, this, ptr,
boost::asio::placeholders::error));

}

tcp_echo_server::tcp_echo_server(boost::asio::io_service& _io_srvice,
boost::asio::ip::tcp::endpoint &_endpoint) :
_acceptor(_io_srvice, _endpoint)
{

start_acceptor(_io_srvice);
}

void tcp_echo_server::action(boost::shared_ptr<tcp_echo_connection> tcp_conn,
const boost::system::error_code& error)
{

try
{
if (!error)
{
boost::asio::ip::tcp::socket& t_socket = tcp_conn->getsocket();
boost::shared_array<char> revdata(new char[128]);
cout << "starting receiving" << endl;
t_socket.async_read_some(
boost::asio::mutable_buffers_1(revdata.get(), 128),
boost::bind(&tcp_echo_server::asy_read_handle, this,
revdata, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
throw boost::system::error_code(error);
}
} catch (std::exception &e)
{
std::cerr << e.what() << std::endl;
acceptor_count--;
} catch (boost::system::error_code& e)
{
cout << "exception catch" << endl;
cout << e.message() << endl;
acceptor_count--;
}

for (int i = 0; i < MAX_ACCEPTOR - acceptor_count; i++)
{
std::cout << "start another" << std::endl;
this->start_acceptor(_acceptor.get_io_service());
}

}

void tcp_echo_server::asy_read_handle(boost::shared_array<char> revdata,
const boost::system::error_code& error, // Result of operation.
std::size_t bytes_transferred // Number of bytes read.
)
{
try
{
if (error)
{
cout << "error:" << error << endl;
throw boost::system::error_code(error);
}
else
{
cout << "str is" << endl;
cout << revdata.get() << endl;
acceptor_count--;
for (int i = 0; i < MAX_ACCEPTOR - acceptor_count; i++)
{
std::cout << "start another" << std::endl;
this->start_acceptor(_acceptor.get_io_service());
}
//std::cout << "start another" << std::endl;
//this->start_acceptor(_acceptor.get_io_service());

}

} catch (std::exception &e)
{
cout << "exception catch" << endl;
cout << e.what() << endl;
acceptor_count--;
} catch (boost::system::error_code& e)
{
cout << "exception catch" << endl;
cout << e.message() << endl;
acceptor_count--;
}

}
int main()
{
try
{
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver _resolver(io_service);
boost::asio::ip::tcp::resolver::query _query("localhost", "13");
boost::asio::ip::tcp::resolver::iterator ite(_resolver.resolve(_query));

boost::asio::ip::tcp::endpoint _endpoint(*ite);
std::cout << _endpoint << std::endl;
tcp_echo_server myserver(io_service, _endpoint);
io_service.run();
} catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}

return 0;
}



client:

#define _WIN32_WINNT 0x0600

#include <tcp_echo_connection.h>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <string>
using namespace std;
using namespace boost::asio::ip;
using namespace boost::asio;
using namespace boost;
class tcp_echo_client;
class tcp_echo_client
{
public:
explicit tcp_echo_client(io_service& _ioservice);
private:

io_service& m_io_service;
void start_asyconnection();
void start_syconnection();
void action(shared_ptr<tcp_echo_connection> tcp_con,
const boost::system::error_code &_err);
void asy_write_handle(const boost::system::error_code& error, // Result of operation.
std::size_t bytes_transferred // Number of bytes written.
);

};

tcp_echo_client::tcp_echo_client(io_service &_ioservice) :
m_io_service(_ioservice)
{
while (1)
start_syconnection();

}

void tcp_echo_client::start_asyconnection()
{
shared_ptr<tcp_echo_connection> tcp_con(
new tcp_echo_connection(m_io_service)); //,tcp::endpoint(tcp::v4(),13));
tcp::socket& t_socket = tcp_con->getsocket();

tcp::resolver _resolver(m_io_service);
tcp::resolver::query _query("localhost", "13");
tcp::resolver::iterator ite(_resolver.resolve(_query));

t_socket.async_connect(
*ite,
boost::bind(&tcp_echo_client::action, this, tcp_con,
boost::asio::placeholders::error));

}

void tcp_echo_client::start_syconnection()
{
shared_ptr<tcp_echo_connection> tcp_con(
new tcp_echo_connection(m_io_service)); //,tcp::endpoint(tcp::v4(),13));
tcp::socket& t_socket = tcp_con->getsocket();

tcp::resolver _resolver(m_io_service);
tcp::resolver::query _query("localhost", "13");
tcp::resolver::iterator ite(_resolver.resolve(_query));
string datastr;
cout << "input something" << endl;
getline(cin, datastr, '\n');

t_socket.connect(*ite);
boost::system::error_code _err;
try
{
cout << "send : " << datastr.c_str() << endl;
t_socket.write_some(
boost::asio::buffer(datastr.c_str(), datastr.size() + 1), _err);
if (_err)
{
throw boost::system::error_code(_err);
}

} catch (std::exception &e)
{
cerr << e.what() << endl;
} catch (boost::system::error_code &e)
{
cerr << e.message() << endl;
}

}

void tcp_echo_client::action(shared_ptr<tcp_echo_connection> tcp_con,
const boost::system::error_code &_err)
{
tcp::socket& t_socket = tcp_con->getsocket();
cout << "input something" << endl;
string inputstr("jh");
cout << "take action" << endl;
try
{

if (!_err)
{
size_t writedata;
t_socket.async_write_some(
asio::buffer(inputstr.c_str(), inputstr.size()),
boost::bind(&tcp_echo_client::asy_write_handle, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
cout << "write " << writedata << endl;
}
else
{
throw boost::system::system_error(_err);
//throw _err;
}
} catch (boost::system::error_code &e)
{
cerr << e.message() << endl;
}
start_asyconnection();

}

void tcp_echo_client::asy_write_handle(const boost::system::error_code& error, // Result of operation.
std::size_t bytes_transferred // Number of bytes written.
)
{

}

int main()
{
boost::asio::io_service myioservice;
try
{

tcp_echo_client a(myioservice);
myioservice.run();
while (1)
;
} catch (std::exception &e)
{
cout << e.what() << endl;
} catch (boost::system::error_code &e)
{
cerr << e.message() << endl;
}

return 0;
}

...全文
627 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
massifking 2012-03-28
  • 打赏
  • 举报
回复
我也碰到过此问题,后来发现是变量生存周期结束导致的.
facat 2011-08-13
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 liugang_12026168 的回复:]

我看了你的程序,先自我总结一下。我要向你学习,你写的很规整。
1、你先这样调试一下,你在客户端发送完数据。sleep一下。最好发送字节数相同,方便调试
2、最有可能的就是接收的服务端的接收字节的原因。我之前也遇到这个原因


如果有什么不懂的可以加入这个群150712146进行交流
[/Quote]

写的规整到说不上,因为eclipse可以帮我自动排版的。
facat 2011-08-13
  • 打赏
  • 举报
回复
解决了,原来是shared_ptr<tcp_echo_connection>变量析构太早的原因。
让变量在asy_read_handle()执行完后析构就行了。
facat 2011-08-12
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 heqinlong 的回复:]

看了你的程序,我也是菜鸟,我有几个疑问

你的服务器是异步的,acceptor之后的回调函数,你用了一个异步读,但是回调函数你又建立一个acceptor,没必要吧!程序用一个acceptor,然后每次建立一个socket即可!
[/Quote]
如果如果只建立一个socket的话,每次就只能有一个client给server发送数据。为了保证可以同时有多个client连接到server上就要多开几个acceptor。我的程序中是保持有5个acceptor开着。
tan625747 2011-08-12
  • 打赏
  • 举报
回复
在收到消息的地方,打印,那部断了
liugang_12026168 2011-08-12
  • 打赏
  • 举报
回复
我看了你的程序,先自我总结一下。我要向你学习,你写的很规整。
1、你先这样调试一下,你在客户端发送完数据。sleep一下。最好发送字节数相同,方便调试
2、最有可能的就是接收的服务端的接收字节的原因。我之前也遇到这个原因


如果有什么不懂的可以加入这个群150712146进行交流
heqinlong 2011-08-11
  • 打赏
  • 举报
回复
看了你的程序,我也是菜鸟,我有几个疑问

你的服务器是异步的,acceptor之后的回调函数,你用了一个异步读,但是回调函数你又建立一个acceptor,没必要吧!程序用一个acceptor,然后每次建立一个socket即可!
facat 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jjajun 的回复:]

是不是几次连续发送的间隔太短了。试着几次发送之间,停顿一下
[/Quote]
我一秒钟发送一次也是一样的。
jjajun 2011-08-11
  • 打赏
  • 举报
回复
是不是几次连续发送的间隔太短了。试着几次发送之间,停顿一下

64,643

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧