简化asio的聊天代码 去除ROOM的设计
所有连接客户端均在同一个ROOM下
/**************************************************************
技术博客
http://www.cnblogs.com/itdef/
技术交流群
群号码:324164944
欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
**************************************************************/
chat message 使用boost自带示例的头文件
#pragma once #include <cstdio> #include <cstdlib> #include <cstring> class chat_message { public: enum { header_length = 4 }; enum { max_body_length = 512 }; chat_message(): body_length_(0) {} const char* data()const { return data_; } char* data() { return data_; } size_t length()const { return header_length + body_length_; } const char* body()const { return data_ + header_length; } char* body() { return data_ + header_length; } size_t body_length()const { return body_length_; } void body_length(size_t new_length) { body_length_ = new_length; if (body_length_ > max_body_length) body_length_ = max_body_length; } bool decode_header() { using namespace std; char header[header_length + 1] = ""; strncat(header, data_, header_length); body_length_ = atoi(header); if (body_length_ > max_body_length) { body_length_ = 0; return false; } return true; } void encode_header() { using namespace std; char header[header_length + 1] = ""; sprintf(header,"%4d",static_cast<int>(body_length_)); memcpy(data_,header,header_length); } private: char data_[header_length + max_body_length]; size_t body_length_; };
// MyChat.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <boost/asio.hpp> #include <set> #include <iostream> #include "chat_message.h" using namespace boost::asio::ip; const int defaultPort = 8899; class chat_session; typedef boost::shared_ptr<chat_session> chat_session_ptr; class chat_session : public boost::enable_shared_from_this<chat_session> { public: chat_session(boost::asio::io_service& io_service, std::set<chat_session_ptr>& sessionList) : socket_(io_service), sessionList_(sessionList) { } ~chat_session() { std::cout << "~chat_session()" << std::endl; } tcp::socket& socket() { return socket_; } void start() { sessionList_.insert(shared_from_this()); boost::asio::async_read(socket_, boost::asio::buffer(read_msg_.data(), chat_message::header_length), boost::bind( &chat_session::handle_read_header, shared_from_this(), boost::asio::placeholders::error)); } void handle_read_header(const boost::system::error_code& error) { if (!error && read_msg_.decode_header() ) { boost::asio::async_read(socket_, boost::asio::buffer(read_msg_.body(), read_msg_.body_length()), boost::bind(&chat_session::handle_read_body, shared_from_this(), boost::asio::placeholders::error)); } else { // occur error,delete from list sessionList_.erase(shared_from_this()); socket_.shutdown(tcp::socket::shutdown_both); socket_.close(); return; } } void handle_read_body(const boost::system::error_code& error) { if (!error) { std::cout << read_msg_.data() << std::endl; boost::asio::async_read(socket_, boost::asio::buffer(read_msg_.data(), chat_message::header_length), boost::bind(&chat_session::handle_read_header, shared_from_this(), boost::asio::placeholders::error)); } else { // occur error,delete from list sessionList_.erase(shared_from_this()); socket_.shutdown(tcp::socket::shutdown_both); socket_.close(); return; } } private: char recvbuf[5]; tcp::socket socket_; chat_message read_msg_; std::set<chat_session_ptr>& sessionList_; }; typedef boost::shared_ptr<chat_session> chat_session_ptr; class chat_server { public: chat_server(boost::asio::io_service& io_service, const tcp::endpoint& endpoint) : io_service_(io_service), acceptor_(io_service, endpoint) { start_accept(); } void start_accept() { chat_session_ptr new_session(new chat_session(io_service_, sessionList_)); acceptor_.async_accept(new_session->socket(), boost::bind(&chat_server::handle_accept, this, new_session, boost::asio::placeholders::error)); } void handle_accept(chat_session_ptr session, const boost::system::error_code& error) { if (!error) { session->start(); } start_accept(); } private: boost::asio::io_service& io_service_; tcp::acceptor acceptor_; std::set<chat_session_ptr> sessionList_; }; typedef boost::shared_ptr<chat_server> chat_server_ptr; int main() { boost::asio::io_service io_service; tcp::endpoint endpoint(tcp::v4(), defaultPort); chat_server chatServer(io_service, endpoint); io_service.run(); return 0; }
测试客户端 chat_message头文件公用
// MyChatCLient.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "chat_message.h" #include <iostream> #include <boost/bind.hpp> #include <boost/asio.hpp> #include <boost/thread/thread.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> using boost::asio::ip::tcp; #define testString "this is a test string......." class chat_client: public boost::enable_shared_from_this<chat_client> { public: chat_client(boost::asio::io_service& io_service, tcp::resolver::iterator endpoint_iterator) : io_service_(io_service), endpoint_iterator_(endpoint_iterator), socket_(io_service) { } void do_close() { socket_.close(); } void Start() { boost::asio::async_connect(socket_, endpoint_iterator_, boost::bind(&chat_client::handle_connect, shared_from_this(), boost::asio::placeholders::error)); } private: void handle_write(const boost::system::error_code& error) { if (!error) { chat_message write_msg_; write_msg_.body_length(strlen(testString) + 1); memcpy(write_msg_.body(), testString, write_msg_.body_length()); write_msg_.encode_header(); boost::asio::async_write(socket_, boost::asio::buffer(write_msg_.data(), write_msg_.length()), boost::bind(&chat_client::handle_write, shared_from_this(), boost::asio::placeholders::error)); } else { do_close(); } } void handle_connect(const boost::system::error_code& error) { if (!error) { chat_message write_msg_; write_msg_.body_length(strlen(testString)+1); memcpy(write_msg_.body(), testString, write_msg_.body_length()); write_msg_.encode_header(); boost::asio::async_write(socket_, boost::asio::buffer(write_msg_.data(), write_msg_.length()), boost::bind(&chat_client::handle_write, shared_from_this(), boost::asio::placeholders::error)); } else { do_close(); } } private: boost::asio::io_service& io_service_; tcp::socket socket_; chat_message write_msg_; tcp::resolver::iterator endpoint_iterator_; }; typedef boost::shared_ptr<chat_client> chat_client_ptr; int main() { boost::asio::io_service io_service; tcp::resolver resolver(io_service); tcp::resolver::query query("127.0.0.1", "8899"); tcp::resolver::iterator iterator = resolver.resolve(query); for (int i = 0; i < 100; i++) { chat_client_ptr a(new chat_client(io_service, iterator)); a->Start(); } io_service.run(); return 0; }
运行效果图
关闭客户端后