64,654
社区成员
发帖
与我相关
我的任务
分享
bool is_expired = false;
using chat_message_queue = std::queue < chat_message >;
std::atomic<int> connection_count = 0;
class session
: public std::enable_shared_from_this<session>
{
public:
session(tcp::socket socket, boost::asio::io_service& IN_io)
: socket_(std::move(socket)), io_service_(IN_io)
{
}
void start()
{
std::cout << "connection from " << socket_.remote_endpoint().address() << std::endl;
do_read_header();
}
void write(const chat_message& msg)
{
write_msgs_ = msg;
do_write(msg.length());
}
void send_uri(const std::string& uri)
{
temp_msg.encode_uri(uri);
write(temp_msg);
}
void send_end()
{
temp_msg.encode_instuction(chat_instructions::page_request_end);
write(temp_msg);
}
private:
void do_read_header()
{
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
[this](boost::system::error_code ec, std::uint32_t /*length*/)
{
if (!ec && read_msg_.decode_header())
{
do_read_body();
}
else
{
socket_.close();
}
});
}
void do_read_body()
{
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
[this](boost::system::error_code ec, std::uint32_t /*length*/)
{
if (!ec)
{
std::string hello, origin;
chat_instructions cur_inst;
std::cout << "message from " << socket_.remote_endpoint().address() << ": " << socket_.remote_endpoint().port()<<": " ;
//std::cout.write(read_msg_.body(), read_msg_.body_length());
read_msg_.decode_instruction(cur_inst);
//std::cout << "\n";
//do_read_header();
switch (cur_inst)
{
case chat_instructions::request_register:
std::cout << "request register" << std::endl;
if (is_expired)
{
temp_msg.encode_instuction(chat_instructions::reject_register);
write(temp_msg);
//write(temp_msg);
connection_count--;
socket_.close();
}
else
{
temp_msg.encode_instuction(chat_instructions::admit_register);
write(temp_msg);
//do_read_header();
}
break;
case chat_instructions::file_send_end:
connection_count--;
std::cout << "file_end" << std::endl;
if (connection_count == 0)
{
std::cout << " everything has finished" << std::endl;
socket_.close();
io_service_.stop();
}
else
{
socket_.close();
}
break;
default:
socket_.close();
break;
}
}
else
{
socket_.close();
}
});
}
void do_write(std::uint32_t length)
{
auto self(shared_from_this());
boost::asio::async_write(socket_, boost::asio::buffer(write_msgs_.data(), length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
do_read_header();
}
});
}
tcp::socket socket_;
boost::asio::io_service& io_service_;
enum
{
max_length = 1024
};
char data_[max_length];
chat_message read_msg_;
chat_message temp_msg;
chat_message write_msgs_;
};
class tcp_message_server
{
public:
tcp_message_server(boost::asio::io_service& io_service, short port)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
socket_(io_service), wait_windows(io_service, boost::posix_time::minutes(1)), io_service_(io_service)
{
wait_windows.async_wait(std::bind(&tcp_message_server::get_douban_album, this,std::placeholders::_1));
do_accept();
}
private:
void do_accept()
{
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
{
if (!ec)
{
connection_count++;
all_session.push_back(std::make_shared<session>(std::move(socket_), io_service_));
all_session.back()->start();
}
do_accept();
});
}
virtual void analyze_uri(const std::string& IN_uri)
{
all_uri.push_back(IN_uri);
//dispatch_uri();
}
void dispatch_uri()
{
int session_size = all_session.size();
for (int i = 0; i < all_uri.size(); i++)
{
all_session[i%session_size]->send_uri(all_uri[i]);
}
for (int i = 0; i < session_size; i++)
{
all_session[i]->send_end();
}
}
void get_douban_album(const boost::system::error_code& error)
{
is_expired = true;
std::cout << "please enter the douban album uri " << std::endl;
std::string album_uri;
std::cin >> album_uri;
analyze_uri(album_uri);
dispatch_uri();
}
std::vector<std::shared_ptr<session>> all_session;
tcp::acceptor acceptor_;
tcp::socket socket_;
boost::asio::deadline_timer wait_windows;
std::vector<std::string> all_uri;
boost::asio::io_service& io_service_;
};
int main(int argc, char* argv [])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: douban chat_server <port>\n";
return 1;
}
boost::asio::io_service io_service;
tcp_message_server s(io_service, std::atoi(argv[1]));
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
typedef std::queue<chat_message> chat_message_queue;
class tcp_message_client
{
public:
tcp::resolver::iterator endpoint_iterator;
std::vector<std::string> all_uri;
tcp_message_client(boost::asio::io_service& io_service,
const std::string& host, const std::string& msg_port)
: io_service_(io_service),
socket_(io_service)
{
tcp::resolver resolver(io_service);
endpoint_iterator = resolver.resolve({ host, msg_port });
do_connect(endpoint_iterator);
}
void write(const chat_message& msg)
{
io_service_.post(
[this, msg]()
{
bool write_in_progress = !write_msgs_.empty();
write_msgs_.push(msg);
if (!write_in_progress)
{
do_write();
}
});
}
void close()
{
io_service_.post([this]()
{
socket_.close();
});
}
private:
void do_connect(tcp::resolver::iterator endpoint_iterator)
{
boost::asio::async_connect(socket_, endpoint_iterator,
[this](boost::system::error_code ec, tcp::resolver::iterator)
{
if (!ec)
{
do_read_header();
}
});
}
void do_read_header()
{
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
[this](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec && read_msg_.decode_header())
{
do_read_body();
}
else
{
socket_.close();
}
});
}
void do_read_body()
{
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
[this](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
std::string cur_uri;
chat_instructions instru_type;
read_msg_.decode_instruction(instru_type);
switch (instru_type)
{
case chat_instructions::reject_register:
std::cout << "request rejected fuck " << std::endl;
socket_.close();
break;
case chat_instructions::admit_register:
std::cout << "request admitted yeah " << std::endl;
do_read_header();
break;
case chat_instructions::page_request:
read_msg_.decode_uri(cur_uri);
std::cout << "get uri from server " << cur_uri << std::endl;
all_uri.push_back(cur_uri);
do_read_header();
break;
case chat_instructions::page_request_end:
std::cout << "this is the end of page" << std::endl;
do_uri();
break;
default:
socket_.close();
}
}
else
{
socket_.close();
}
});
}
virtual void do_uri()
{
std::cout << "sending eof" << std::endl;
send_eof();
}
void send_eof()
{
chat_message end_of_file;
end_of_file.encode_instuction(chat_instructions::file_send_end);
write(end_of_file);
close();
}
void do_write()
{
boost::asio::async_write(socket_,
boost::asio::buffer(write_msgs_.front().data(),
write_msgs_.front().length()),
[this](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
write_msgs_.pop();
if (!write_msgs_.empty())
{
do_write();
}
}
else
{
socket_.close();
}
});
}
private:
boost::asio::io_service& io_service_;
tcp::socket socket_;
chat_message read_msg_;
chat_message_queue write_msgs_;
};
int main(int argc,char** argv)
{
try
{
if (argc != 3)
{
std::cerr << "Usage: chat_client <host> <port>\n";
return 1;
}
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
//auto endpoint_iterator = resolver.resolve({ "127.0.0.1", "1345" });
tcp_message_client c(io_service, "127.0.0.1","1345");
std::thread t([&io_service]()
{
io_service.run();
});
char line[chat_message::max_body_length + 1];
chat_message reg_msg;
reg_msg.encode_instuction(chat_instructions::request_register);
c.write(reg_msg);
t.join();
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}