一、服务器端源代码
3. Connection.cpp (每个客户端连接分别对应一个CConnection对象)
#include "Connection.h"
#include "ConnectionManager.h"
#include <iostream>
#include <vector>
#include <boost/bind.hpp>
using namespace std;
CConnection::CConnection(boost::asio::io_service& io_service)
: m_socket(io_service)
{
}
boost::asio::ip::tcp::socket& CConnection::Socket()
{
return m_socket;
}
void CConnection::Start()
{
cout<<"CConnection::Start() user:"<<m_registerName<<endl;
m_socket.async_read_some(boost::asio::buffer(m_buffer),
boost::bind(&CConnection::handleRead, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void CConnection::handleRead(const boost::system::error_code& e, size_t bytes_transferred)
{
cout<<"CConnection::handleRead() user:"<<m_registerName<<endl;
if (!e)
{
MSG_TYPE type = m_reqHandler.ParseMsg(m_buffer.data(), bytes_transferred);
if(Register_Msg == type)
{
string strName = m_reqHandler.GetRegisterName(m_buffer.data(), bytes_transferred);
bool b = addConnetion(strName, shared_from_this());
if(b)
{
m_registerName = strName;
handleRegisterSuccess();
}
else
{
handleRegisterError();
}
}
else if(Send_Msg == type)
{
string toName = m_reqHandler.GetToUserName(m_buffer.data(), bytes_transferred);
handleSendMsg(m_registerName, toName, bytes_transferred);
}
else
{
handleWrongMsg();
}
}
else
{
cout << "handleRead Error: " << e.message() << "\n";
}
}
bool CConnection::addConnetion(const string& strUserName, Connection_ptr ptrConn)
{
cout<<"CConnection::addConnetion() user:"<<m_registerName<<endl;
return CConnetionManager::Instance()->AddConnection(strUserName, ptrConn);
}
void CConnection::handleRegisterSuccess()
{
cout<<"CConnection::handleRegisterSuccess() user:"<<m_registerName<<endl;
string strData("Register Success! \nAll users are: ");
set<string> mUsers;
CConnetionManager::Instance()->GetClientList(mUsers);
set<string>::iterator iter = mUsers.begin();
for(; iter!=mUsers.end(); ++iter)
{
strData.append(*iter);
strData.append(" ");
}
cout<<"handleRegisterSuccess::strData="<<strData<<endl;
boost::asio::async_write(m_socket, boost::asio::buffer(strData),
boost::bind(&CConnection::handleWrite, shared_from_this(), boost::asio::placeholders::error));
}
void CConnection::handleRegisterError()
{
cout<<"CConnection::handleRegisterError() user:"<<m_registerName<<endl;
string strData("Register Error! Maybe there is a same username,input new one pls.\n ");
boost::asio::async_write(m_socket,boost::asio::buffer(strData),
boost::bind(&CConnection::handleWrite, shared_from_this(), boost::asio::placeholders::error));
}
void CConnection::handleSendMsg(const string& strFromUser, const string& strToUser, size_t dataSize)
{
cout<<"CConnection::handleSendMsg() user:"<<m_registerName<<endl;
string strData("From:");
strData.append(strFromUser);
strData.append(m_reqHandler.GetMsgContent(m_buffer.data(), dataSize));
cout<<"handleSendMsg::strData="<<strData<<endl;
if(strcmp(strToUser.c_str(),"all"))
{
CConnetionManager::Instance()->GetConnection(strToUser)->sendMsg(strData);
}
else
{
std::map<std::string,Connection_ptr>& mapConn = CConnetionManager::Instance()->GetConnectionsMap();
std::map<std::string,Connection_ptr>::iterator iter = mapConn.begin();
for(; iter!=mapConn.end(); ++iter)
{
if(iter->first == strFromUser)
continue;
iter->second->sendMsg(strData);
}
}
boost::system::error_code err;
handleWrite(err);
}
void CConnection::handleWrongMsg()
{
cout<<"CConnection::handleWrongMsg() user:"<<m_registerName<<endl;
string strData("The input format error! Again pls.\n ");
boost::asio::async_write(m_socket,boost::asio::buffer(strData),
boost::bind(&CConnection::handleWrite, shared_from_this(), boost::asio::placeholders::error));
}
void CConnection::handleWrite(const boost::system::error_code& e)
{
cout<<"CConnection::handleWrite() user:"<<m_registerName<<endl;
bufferClear();
if (!e)
{
m_socket.async_read_some(boost::asio::buffer(m_buffer),
boost::bind(&CConnection::handleRead, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
cout << "handleWrite Error: " << e.message() << "\n";
m_socket.close();
}
}
void CConnection::bufferClear()
{
cout<<"CConnection::bufferClear() user:"<<m_registerName<<endl;
int size = m_buffer.size();
if(size != 0)
{
for(int i=0; i<size; i++)
{
m_buffer[i] = '\0';
}
}
}
void CConnection::sendMsg(const string &strData)
{
cout<<"CConnection::sendMsg() user:"<<m_registerName<<endl;
boost::asio::async_write(m_socket,boost::asio::buffer(strData),
boost::bind(&CConnection::handleWrite, shared_from_this(), boost::asio::placeholders::error));
}
4. ConnectionManager.cpp (对每个连接的管理)
#include "ConnectionManager.h"
#include <iostream>
using namespace std;
CConnetionManager * CConnetionManager::sm_pInstance=NULL;
CConnetionManager * CConnetionManager::Instance()
{
if(sm_pInstance==NULL)
{
sm_pInstance=new CConnetionManager;
}
return sm_pInstance;
}
CConnetionManager::CConnetionManager()
{
}
bool CConnetionManager::AddConnection(const std::string& strUserName, Connection_ptr ptrConn)
{
cout<<"CConnetionManager::AddConnection() , strUserName="<<strUserName<<endl;
boost::lock_guard<boost::mutex> guard(m_mut);
if(m_mapConns.find(strUserName)==m_mapConns.end())
{
m_mapConns[strUserName]=ptrConn;
return true;
}
return false;
}
Connection_ptr CConnetionManager::GetConnection(const std::string& strUserName)
{
cout<<"CConnetionManager::GetConnection() , strUserName="<<strUserName<<endl;
Connection_ptr ptrConn;
boost::lock_guard<boost::mutex> guard(m_mut);
map<string,Connection_ptr>::iterator itr=m_mapConns.find(strUserName);
if(itr!=m_mapConns.end())
{
ptrConn=itr->second;
}
return ptrConn;
}
void CConnetionManager::GetClientList(std::set<string>& userNames)
{
cout<<"CConnetionManager::GetClientList()"<<endl;
boost::lock_guard<boost::mutex> guard(m_mut);
map<string,Connection_ptr>::iterator iter = m_mapConns.begin();
for(; iter!=m_mapConns.end(); ++iter)
{
userNames.insert(iter->first);
}
}
std::map<std::string,Connection_ptr>& CConnetionManager::GetConnectionsMap()
{
boost::lock_guard<boost::mutex> guard(m_mut);
return m_mapConns;
}
void CConnetionManager::DelConnection(const std::string& strUserName)
{
cout<<"CConnetionManager::DelConnection()"<<endl;
boost::lock_guard<boost::mutex> guard(m_mut);
map<string,Connection_ptr>::iterator itr=m_mapConns.find(strUserName);
if(itr!=m_mapConns.end())
{
m_mapConns.erase(itr);
}
}
CConnetionManager::~CConnetionManager()
{
while(!m_mapConns.empty())
{
m_mapConns.erase(m_mapConns.begin());
}
}
待续...