我有以下服务器代码。等待客户端连接,一旦客户端连接它将启动从客户端连接接收数据的线程,主线程将等待另一个客户端连接。这段代码工作正常。
现在我必须指定服务器将等待一段时间,比如10秒,以便从连接的客户端接收数据。如果在指定时间内没有收到数据,服务器将关闭通信。我已经实现了相同的计时器但不知何故它不起作用,并且在经过一段时间后没有调用timer_callback
。
#include <ctime>
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <sys/socket.h>
#include <unistd.h>
#include <string>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
using namespace std;
using boost::asio::ip::tcp;
void run(boost::shared_ptr<tcp::socket> my_socket)
{
while (1)
{
char buf[128];
boost::system::error_code error;
size_t len = my_socket->read_some(boost::asio::buffer(buf, 128), error);
std::cout << "len : " << len << std::endl;
if (error == boost::asio::error::eof)
{
cout << "\t(boost::asio::error::eof)" << endl;
if (my_socket->is_open())
{
boost::system::error_code ec;
cout << "\tSocket closing" << endl;
my_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
cout << "\tShutdown " << ec.message() << endl;
//cout << "normal close : " << ::close(my_socket->native_handle()) << endl;
my_socket->close(ec);
cout << "\tSocket closed" << endl;
}
break; // Connection closed cleanly by peer.
}
else if (error)
{
std::cout << "Exception : " << error.message() << std::endl;
break;
}
else
{
for (unsigned int i = 0; i < len; i++)
printf("%02x ", buf[i] & 0xFF);
printf("\n");
}
}
}
void timer_callback(boost::shared_ptr<tcp::socket> my_socket, const boost::system::error_code& error)
{
std::cout << "timer expired.... " << std::endl;
if (error != boost::asio::error::operation_aborted)
{
// do something
std::string str_error = "timer expired " + error.message();
my_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
my_socket->close();
}
else
{
std::cout << "timer cancelled ..." << error.message() << std::endl;
}
}
int main()
{
const int S = 1000;
vector<boost::shared_ptr<boost::thread> > arr_thr(S);
boost::asio::io_service io_service;
boost::asio::deadline_timer timer(io_service);
try
{
for (uint32_t i = 0;; i++)
{
tcp::endpoint endpoint(tcp::v6(), 10001);
boost::shared_ptr<tcp::socket> my_socket(new tcp::socket(io_service));
tcp::endpoint end_type;
tcp::acceptor acceptor(io_service, endpoint);
std::cout << "before accept" << endl;
acceptor.accept(*my_socket, end_type);
usleep(10000);
std::cout << "connected... hdl : " << my_socket->native_handle() << std::endl;
boost::asio::ip::address addr = end_type.address();
std::string sClientIp = addr.to_string();
std::cout << "\tclient IP : " << sClientIp << std::endl;
timer.expires_from_now(boost::posix_time::seconds(10));
timer.async_wait(
boost::bind(&timer_callback, my_socket, boost::asio::placeholders::error));
arr_thr[i] = boost::shared_ptr<boost::thread>(new boost::thread(&run, my_socket));
}
} catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
答案 0 :(得分:3)
看起来你想从主线程中执行accept
和async_wait
并在单独的线程上执行一些阻塞读取。
这种方法存在多个问题。首先你的accept
被阻止,所以当主线程等待接受时,计时器无法运行。此外,无法调用io_service
run
或poll
,因此永远不会调用异步处理程序。
如果您想在同一个帖子中将其与async_accept
混合使用,则必须使用async_wait
。
但是,您仍然无法取消另一个线程上的阻塞读取。 documentation表示同时使用多个线程的套接字是不安全的(共享对象:不安全)。
我建议您使用完全异步设计。