聊天服务器——封装服务器类

封装服务器类的目的是希望全局只有一个服务器

IMServer.h

#include <list>
​
#include "net/EventLoop.h"
#include "net/EventLoopThread.h"
#include "net/EventLoopThreadPool.h"
#include "net/TcpServer.h"
#include "base/Logging.h"
#include "ClientSession.h"
#include <mutex>
#include <iostream>
​
using namespace muduo;
using namespace muduo::net;
using namespace std;
​
class IMServer final //final表示该类不可能派生子类
{
public:
    IMServer() = default;
    IMServer(const IMServer&) = delete;//禁止使用此函数
    ~IMServer() = default;
    IMServer& operator=(const IMServer&) = delete;//禁用此函数
    bool Init(const string& ip, short port, EventLoop* loop);
protected:
    void OnConnection(const TcpConnectionPtr& conn);
    void OnClose(const TcpConnectionPtr& conn);
private:
    shared_ptr<TcpServer>  m_server;
    map<string, ClientSessionPtr> m_mapclient;
    //std::list<TcpConnectionPtr> m_lstConn;
    mutex m_sessionlock;//保护m_mapclient的操作
};
typedef pair<string, ClientSessionPtr> ConnPair;
typedef map<string, ClientSessionPtr>::iterator ConnIter;

IMServer.cpp

#include "IMServer.h"
using namespace std::placeholders;
​
bool IMServer::Init(const std::string& ip, short port, EventLoop* loop)
{
    InetAddress addr(ip, port);
    m_server.reset(new TcpServer(loop, addr, "chatserver", TcpServer::kReusePort));
    m_server->setConnectionCallback(std::bind(&IMServer::OnConnection, this, _1));
    m_server->start();
    return true;
}
​
void IMServer::OnConnection(const TcpConnectionPtr& conn)
{
    if (conn->connected()) {
        ClientSessionPtr client(new ClientSession(conn));
        {
           //防止OnConnection在多个线程中插入出现问题
           std::lock_guard<std::mutex> guard(m_sessionlock);
           m_mapclient.insert(ConnPair((std::string) * client, client));
           //m_lstConn.push_back(client);
         }
     }
     else {
         OnClose(conn);
     }
}
​
void IMServer::OnClose(const TcpConnectionPtr& conn)
{
    //TODO:处理这个连接,找到这个连接,然后进行关闭
    stringstream ss;
    ss << (void*)conn.get();
    ConnIter iter = m_mapclient.find(ss.str());
    if (iter != m_mapclient.end()) {
       //TODO:关闭连接的操作
       m_mapclient.erase(iter);
    }
    else {
       //TODO:有问题的连接
       cout << conn->name() << std::endl;
    }
}

ClientSession.h

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
​
using namespace muduo;
using namespace muduo::net;
using namespace boost::uuids;
using namespace std::placeholders
​
class ClientSession
{
public:
    ClientSession(const TcpConnectionPtr& conn);
    //为了控制生命周期,防止提前销毁,或者销毁之后,重复销毁
    ClientSession(const ClientSession&) = delete;
    ClientSession& operator=(const ClientSession&) = delete;
    ~ClientSession();
​
    operator std::string()
    {
        return m_sessionid;
    }
    
    void OnRead(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time);
    void Send(const std::string& buf);
    
private:
    string m_sessionid;
   
};
​
typedef std::shared_ptr<ClientSession> ClientSessionPtr;

ClientSession.cpp

#include "ClientSession.h"
​
ClientSessionPtr::CientSessionPtr(const TcpConnectionPtr& conn)
{
   //此处就是两个括号,第一个表示构造对象,第二个表示()运算符重载
   m_sessionid = to_string(random_generator()());
   //到时候研究一下为什么这里用TcpConnectionPtr*,而不是TcpConnectionPtr
   TcpConnectionPtr* client = const_cast<TcpConnectionPtr*>(&conn);
   //使用const_cast消除const限定符
   const_cast<std::string>(&conn->name()) = m_sessionid;
   (*client)->setMessageCallback(std::bind(&ClientSession::OnRead,this,_1,_2,_3));
}
​
void ClientSessionPtr::OnRead(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time)
{
    //业务代码
}
​
void ClientSession::Send(const std::string& buf)
{
    //发送数据
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值