Mysql
需要安装mysql和mysql的开发包,ubuntu下安装开发包的命令是
sudo apt-get install libmysqlclient-dev
Mysql.h
#ifndef DB_H
#define DB_H
#include <mysql/mysql.h>
#include <string>
class MySQL {
public:
MySQL() ;
~MySQL() ;
bool connect() ;
bool update(std::string sql) ;
MYSQL_RES* query(std::string sql) ;
MYSQL* getConnection() ;
private:
MYSQL* _conn ;
} ;
#endif
Mysql.cpp
#include "db.h"
#include <muduo/base/Logging.h>
#include <string>
#include <iostream>
static std::string server = "127.0.0.1" ;
static std::string user = "root" ;
static std::string password = "123456" ;
static std::string dbname = "chat" ;
MySQL::MySQL(){
_conn = mysql_init(nullptr) ;
}
MySQL::~MySQL() {
if(_conn != nullptr ) {
mysql_close(_conn) ;
}
}
bool MySQL::connect() {
MYSQL* p = mysql_real_connect(_conn , server.c_str() , user.c_str()
, password.c_str() , dbname.c_str() , 3306 , nullptr , 0 ) ;
if(p != nullptr ) {
// mysql_query(_conn , "set names gbk") ;
LOG_INFO << "connection mysql database sucess!" ; // 这里实现的是一个简易的宏日志系统,不影响代码逻辑
} else {
LOG_INFO << __FILE__ << ":" << __LINE__ << ":" << "连接失败,请稍后重试" ;
std::cerr << mysql_error(_conn) << std::endl ;
}
return p ;
}
bool MySQL::update(std::string sql) {
if(mysql_query(_conn , sql.c_str() ) ) {
LOG_INFO << __FILE__ << ":" << __LINE__ << ":" << sql << "更新失败" ;
return false ;
}
return true ;
}
MYSQL_RES* MySQL::query(std::string sql) {
if(mysql_query(_conn , sql.c_str())) {
LOG_INFO << __FILE__ << ":" << __LINE__ << ":" << sql << "查询失败" ;
return nullptr ;
}
return mysql_use_result(_conn) ;
}
MYSQL* MySQL::getConnection(){
return _conn ;
}
Zookeeper
Zookeepr.h
在使用的时候一定要 -lzookeeper_mt 链接zookeeper的动态库
#pragma once
#include <semaphore.h>
#include <zookeeper/zookeeper.h>
#include <string>
class ZkClient {
public :
ZkClient() ;
~ZkClient() ;
void Start() ;
void Create(const char* path , const char * data , int datalen , int state = 0 ) ;
std::string GetData(const char* path ) ;
private:
// zk的客户端的句柄
zhandle_t* m_zhandle ;
} ;
Zookeeper.cpp
#include "rpczookeeperutil.h"
#include "rpcapplication.h"
#include "rpcserverlog.h"
#include <semaphore>
// 当服务端向客户端发送成功的消息的时候,这个函数会被回调
void watcher(zhandle_t *zh, int type, int state, const char *path,void *watcherCtx) {
if(type == ZOO_SESSION_EVENT ) {
if(state == ZOO_CONNECTED_STATE ) {
sem_t* sem = (sem_t*)zoo_get_context(zh) ;
sem_post(sem) ;
}
}
}
ZkClient::ZkClient(): m_zhandle(nullptr) {
}
ZkClient::~ZkClient(){
if(m_zhandle != nullptr ) {
zookeeper_close(m_zhandle) ;
}
}
// 客户端异步连接 zkServer服务器
void ZkClient::Start() {
std::pair<std::string , int> info = RpcApplication::GetInstance().GetZookeeperInfo() ;
std::string host = info.first , port = std::to_string(info.second) ;
std::string connstr = host + ":" + port ;
/*
如果链接的是zookeeper_mt 多线程版本的库
在调用zookeeper_init的时候是异步的,有多个线程:
API调用线程,就是当前线程
在函数内部通过调用pthread_create API 接口创建另外两个线程: 网络I/O线程(使用poll) , watcher 回调线程
*/
m_zhandle = zookeeper_init(connstr.c_str() , watcher , 30000 , nullptr , nullptr , 0) ;
if(m_zhandle == nullptr ) {
LOG_INFO("connect to zookeeper server:%s failed..." , ERROR , connstr.c_str() ) ;
exit(EXIT_FAILURE) ;
}
sem_t sem ; // 用于判断是否连接成功
sem_init(&sem , 0 , 0 ) ;
zoo_set_context(m_zhandle , &sem) ;
sem_wait(&sem) ; // 一直阻塞,直到watcher 成功被调用,表示连接成功
LOG_INFO("zookeeper_init sucess!" , INFO) ;
}
// 创建节点并给节点赋值
void ZkClient::Create(const char* path , const char * data , int datalen , int state ) {
char path_buffer[1024] ;
int bufferlen = sizeof(path_buffer) ;
int flag ;
flag = zoo_exists(m_zhandle , path , 0 , nullptr ) ; // 判断当前节点是否存在
if(ZNONODE == flag ) {
flag = zoo_create(m_zhandle , path , data , datalen , &ZOO_OPEN_ACL_UNSAFE , state , path_buffer , bufferlen ) ;
if(flag == ZOK) {
LOG_INFO("znode create sucess.... path:%s" , INFO , path) ;
}else {
LOG_INFO("flag: %d znode create error.... path: %s" , ERROR , flag , path ) ;
exit(EXIT_FAILURE) ;
}
}
}
// 获取节点上的数据
std::string ZkClient::GetData(const char* path ) {
char buffer[1024] ;
int bufferlen = sizeof(buffer) ;
int flag = zoo_get(m_zhandle , path , 0 , buffer , &bufferlen , nullptr ) ;
if(flag != ZOK) {
LOG_INFO("get znode error.... path: %s" , ERROR , path ) ;
exit(EXIT_FAILURE) ;
}
return buffer ;
}
Redis
git clone https://github.com/redis/hiredis 从github上下载hiredis客户端,进行源码
编译安装
cd hiredis
make
sudo make install
sudo ldconfig /usr/local/lib
在使用的时候需要 -lhiredis 链接动态库文件
这里的封装的只是对redis上的数据进行简单的增删改查,并不涉及复杂的操作
Redis.h
#pragma once
#include <hiredis/hiredis.h>
#include <thread>
#include <functional>
#include <string>
#include <iostream>
class Redis {
public:
Redis() ;
~Redis() ;
void Connect() ;
void RegisterRpcAddress(std::string service , std::string method , std::string address ) ;
std::string GetAddress(std::string service , std::string method) ;
std::string RedisCommand(std::string command , std::string key , std::string value ) ;
private:
redisContext* conn ;
} ;
Redis.cpp
#include "rpcredisutil.h"
#include <iostream>
#include "rpcapplication.h"
Redis::Redis(): conn(nullptr) {}
Redis::~Redis() {
if(conn != nullptr ) {
redisFree(conn) ;
}
}
void Redis::Connect() {
std::pair<std::string , int> redisInfo = RpcApplication::GetInstance().GetRedisInfo() ;
std::string ip = redisInfo.first ;
int port = redisInfo.second ;
conn = redisConnect( ip.c_str() , port ) ;
if (conn->err)
{
std::cout << __FILE__ << __LINE__ << "init redis failed..." << std::endl ;
redisFree(conn);
exit(EXIT_FAILURE) ;
}
}
void Redis::RegisterRpcAddress(std::string service , std::string method , std::string address ) {
redisReply * reply = (redisReply* ) redisCommand(conn, "hset %s %s %s"
, service.c_str() , method.c_str() , address.c_str()
);
if(reply->type == REDIS_REPLY_ERROR) {
std::cout << __FILE__ << __LINE__ << reply->str << std::endl ;
freeReplyObject(reply) ;
exit(EXIT_FAILURE) ;
}
freeReplyObject(reply) ;
}
std::string Redis::GetAddress(std::string service , std::string method) {
redisReply * reply = (redisReply* ) redisCommand(conn, "hget %s %s"
, service.c_str() , method.c_str()
);
if(reply->type == REDIS_REPLY_ERROR) {
std::cout << __FILE__ << __LINE__ << reply->str << std::endl ;
freeReplyObject(reply) ;
exit(EXIT_FAILURE) ;
}
std::string addr = reply->str ;
freeReplyObject(reply) ;
return addr ; // 获取到指定的ip:port
}
std::string Redis::RedisCommand(std::string command , std::string key , std::string value ) {
redisReply * reply ;
if(value == "") {
reply =(redisReply* ) redisCommand(conn , "%s %s" ,
command.c_str() , key.c_str() ) ;
}else {
reply =(redisReply* ) redisCommand(conn , "%s %s %s" ,
command.c_str() , key.c_str() , value.c_str()
);
}
if(reply->type == REDIS_REPLY_ERROR) {
std::cout << __FILE__ << __LINE__ << reply->str << std::endl ;
freeReplyObject(reply) ;
exit(EXIT_FAILURE) ;
}
std::string answer = reply->str ;
freeReplyObject(reply) ;
return answer ;
}