金慶的專(zhuān)欄
C++博客
::
首頁(yè)
::
新隨筆
::
聯(lián)系
::
聚合
::
管理
::
423 隨筆 :: 0 文章 :: 454 評(píng)論 :: 0 Trackbacks
公告
我的隨筆
我的評(píng)論
我參與的隨筆
留言簿
(12)
給我留言
查看公開(kāi)留言
查看私人留言
隨筆分類(lèi)
(502)
1. C/C++(166)
(rss)
2. 網(wǎng)游開(kāi)發(fā)(108)
(rss)
3. Golang(20)
(rss)
4. Linux/Unix(30)
(rss)
5. 軟工與管理(44)
(rss)
6. Python(23)
(rss)
7. Erlang(18)
(rss)
8. Rust(16)
(rss)
9. 其它(77)
(rss)
隨筆檔案
(423)
2023年1月 (1)
2022年11月 (1)
2022年10月 (2)
2022年9月 (1)
2022年4月 (6)
2022年1月 (2)
2021年12月 (4)
2021年11月 (6)
2021年10月 (2)
2021年9月 (2)
2021年8月 (7)
2021年7月 (2)
2021年5月 (2)
2021年3月 (1)
2021年2月 (2)
2021年1月 (1)
2020年12月 (1)
2020年10月 (1)
2020年9月 (5)
2020年8月 (1)
2020年7月 (1)
2020年6月 (1)
2020年4月 (2)
2020年3月 (3)
2020年2月 (3)
2020年1月 (1)
2019年12月 (1)
2019年9月 (2)
2019年4月 (2)
2019年1月 (1)
2018年12月 (1)
2018年11月 (3)
2018年10月 (1)
2018年9月 (3)
2018年8月 (3)
2018年7月 (2)
2018年6月 (4)
2018年5月 (4)
2018年4月 (4)
2018年3月 (1)
2018年1月 (2)
2017年12月 (2)
2017年11月 (3)
2017年10月 (3)
2017年8月 (7)
2017年7月 (1)
2017年6月 (1)
2017年5月 (3)
2017年4月 (3)
2017年3月 (3)
2017年2月 (2)
2017年1月 (2)
2016年12月 (5)
2016年11月 (2)
2016年10月 (2)
2016年9月 (1)
2016年8月 (6)
2016年7月 (3)
2016年6月 (2)
2016年5月 (4)
2016年4月 (2)
2016年3月 (2)
2016年1月 (3)
2015年12月 (2)
2015年11月 (2)
2015年10月 (1)
2015年8月 (2)
2015年7月 (1)
2015年6月 (1)
2015年5月 (4)
2015年4月 (3)
2015年3月 (4)
2015年2月 (5)
2015年1月 (4)
2014年12月 (3)
2014年11月 (3)
2014年10月 (2)
2014年9月 (3)
2014年8月 (1)
2014年4月 (4)
2014年3月 (1)
2014年2月 (4)
2014年1月 (5)
2013年12月 (5)
2013年11月 (5)
2013年9月 (2)
2013年8月 (2)
2013年7月 (2)
2013年6月 (2)
2013年5月 (1)
2013年1月 (2)
2012年12月 (1)
2012年11月 (1)
2012年9月 (1)
2012年8月 (3)
2012年7月 (2)
2012年6月 (1)
2012年4月 (3)
2012年3月 (2)
2012年2月 (3)
2012年1月 (2)
2011年11月 (2)
2011年10月 (3)
2011年9月 (2)
2011年8月 (2)
2011年7月 (3)
2011年6月 (2)
2011年5月 (3)
2011年1月 (2)
2010年12月 (1)
2010年11月 (2)
2010年10月 (2)
2010年9月 (3)
2010年8月 (2)
2010年7月 (3)
2010年6月 (1)
2010年5月 (3)
2010年4月 (3)
2010年3月 (5)
2010年2月 (4)
2010年1月 (4)
2009年12月 (2)
2009年11月 (3)
2009年10月 (4)
2009年9月 (3)
2009年8月 (2)
2009年7月 (4)
2009年6月 (1)
2009年5月 (3)
2009年4月 (4)
2009年3月 (2)
2009年2月 (5)
2009年1月 (1)
2008年12月 (7)
2008年11月 (4)
2008年10月 (1)
2008年9月 (3)
2008年8月 (4)
2008年7月 (3)
2008年6月 (4)
2008年5月 (6)
2008年4月 (7)
2008年3月 (6)
2008年1月 (5)
2007年12月 (7)
2007年11月 (4)
2007年10月 (5)
2007年9月 (6)
2007年8月 (8)
2007年7月 (5)
相冊(cè)
公告照片
搜索
積分與排名
積分 - 656590
排名 - 25
最新評(píng)論
1.?re: boost::asio::spawn 將一統(tǒng)C++網(wǎng)絡(luò)庫(kù)
asio 成為C++首選網(wǎng)絡(luò)庫(kù)
--linda
2.?re: log4cxx中文輸出錯(cuò)誤補(bǔ)丁
評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
--金慶
3.?re: mingw編譯OrzNet
能發(fā)送一個(gè)mingw編譯好的OrzNet庫(kù)給我嗎? liuweiqcxy@163.com
謝謝!
--劉威
4.?re: log4cxx中文輸出錯(cuò)誤補(bǔ)丁
評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
--bigbad
5.?re: log4cxx中文輸出錯(cuò)誤補(bǔ)丁
評(píng)論內(nèi)容較長(zhǎng),點(diǎn)擊標(biāo)題查看
--bigbad
閱讀排行榜
1.?"multiple definition of" 錯(cuò)誤(11032)
2.?SVN中邪惡的replace(10955)
3.?VS2005編譯libevent(10413)
4.?混音算法的學(xué)習(xí)與研究(10203)
5.?C調(diào)用lua腳本的效率測(cè)試(9007)
評(píng)論排行榜
1.?VC6正在被拋棄(35)
2.?VS2005編譯libevent(21)
3.?"multiple definition of" 錯(cuò)誤(18)
4.?C++引用優(yōu)于指針(17)
5.?ACE與ASIO之間關(guān)于Socket編程的比較(16)
hiredis異步接口封裝并導(dǎo)出到Lua
hiredis異步接口封裝并導(dǎo)出到Lua
(金慶的專(zhuān)欄 2017.1)
hiredis 不支持 Windows, Windows 下使用 wasppdotorg / hiredis-for-windows 。
Linux 下仍是 redis/hiredis。
hiredis-for-windows 是以 hiredis 0.13.3 為基礎(chǔ)移植的。
hiredis-for-windows 需要稍加修正:
* 去除 inline 宏
* TCP_NODELAY 改在連接之前設(shè)置。
詳見(jiàn)其Issue.
Cluster 支持采用 shinberg/cpp-hiredis-cluster。這是個(gè)CPP庫(kù),支持異步,
要求 hiredis >= 0.12.0。
jinq0123/cpp-hiredis-cluster 在 develop 分支上更改了接口,讓它更好用。
因?yàn)榫W(wǎng)絡(luò)庫(kù)是boost asio, 所以需要asio適配器,采用 jinq0123/hiredis-boostasio-adapter。
cpp-hiredis-cluster 提供的是統(tǒng)一的Command接口,接收字符串命令,返回 redisReply.
對(duì)于常用命令,需要更簡(jiǎn)單的接口。
在Lua手游服務(wù)器代碼中新建CRedis類(lèi),封裝 cpp-hiredis-cluster,
為常用redis命令封裝更好用的接口。
CRedis類(lèi)封裝了asio, 接口是根據(jù)應(yīng)用需要定義的,所以是專(zhuān)用接口,
不在 cpp-hiredis-cluster 中實(shí)現(xiàn)。
bool CRedis::Init(io_service& rIos, const std::string& sHost, uint16_t uPort)
創(chuàng)建 RedisCluster 對(duì)象。
io_service 用于創(chuàng)建一個(gè) redis 事件適配器,
RedisCluster創(chuàng)建需要一個(gè)適配器。
sHost, uPort 用于初始化連接redis cluster, 獲取集群信息。
using Cmd = RedisCluster::AsyncHiredisCommand;
bool CRedis::Init(io_service& rIos, const std::string& sHost, uint16_t uPort)
{
m_pAdapter.reset(new Adapter(rIos));
try
{
m_pCluster.reset(Cmd::createCluster("127.0.0.1", 7000, *m_pAdapter));
}
catch (const RedisCluster::ClusterException &e)
{
LOG_ERROR("Cluster exception: " << e.what());
return false;
}
return true;
}
static Cmd::Action handleException(const RedisCluster::ClusterException &exception,
RedisCluster::HiredisProcess::processState state)
{
// Check the exception type.
// Retry in case of non-critical exceptions.
if (!dynamic_cast<const RedisCluster::CriticalException*>(&exception))
{
LOG_WARN("Exception in processing async redis callback: "
<< exception.what() << " Retry...");
// retry to send a command to redis node
return Cmd::RETRY;
}
LOG_ERROR("Critical exception in processing async redis callback: "
<< exception.what());
return Cmd::FINISH;
}
static void handleSetReply(const redisReply &reply, const CRedis::SetCb& setCb)
{
if (!setCb) return;
if (reply.type == REDIS_REPLY_STATUS)
{
const std::string OK("OK");
if (OK == reply.str)
{
setCb(true);
return;
}
}
LOG_WARN("Set reply: " << reply.str);
setCb(false);
}
void CRedis::Set(const string& sKey, const string& sValue, const SetCb& setCb)
{
assert(m_pCluster);
Cmd::commandf2(*m_pCluster, sKey,
[setCb](const redisReply& reply) {
handleSetReply(reply, setCb);
},
handleException,
"set %s %s", sKey.c_str(), sValue.c_str());
}
static void handleGetReply(const redisReply& reply,
const CRedis::ReplyStringCb& hdlStrReply)
{
if (!hdlStrReply) return;
using Rt = CRedis::ReplyType;
if (reply.type == REDIS_REPLY_NIL)
{
hdlStrReply(Rt::NIL, "");
return;
}
std::string sReply(reply.str, reply.len);
if (reply.type == REDIS_REPLY_STRING)
hdlStrReply(Rt::OK, sReply);
else
hdlStrReply(Rt::ERR, sReply);
}
void CRedis::Get(const std::string& sKey, const ReplyStringCb& hdlStrRepl)
{
assert(m_pCluster);
Cmd::commandf2(*m_pCluster, sKey,
[hdlStrRepl](const redisReply& reply) {
handleGetReply(reply, hdlStrRepl);
},
handleException,
"get %s", sKey.c_str());
}
handleException 是Cmd::command() 接口中需要的異常處理,這里是盡量重試。
Cmd::command() 中的第3個(gè)參數(shù)是 redis 應(yīng)答的回調(diào),讀取 redisReply, 然后觸發(fā)命令的回調(diào)。
CRedis::Get() 執(zhí)行 redis GET 命令,固定1個(gè)參數(shù),返回是字符串,nil, 或錯(cuò)誤。
enum class ReplyType
{
OK = 0, // redis replys string/integer/array
NIL = 1, // redis replys nil
ERR = 2, // redis replys error status
};
// 簡(jiǎn)單的常用命令會(huì)自動(dòng)解析reply, 使用更易用的回調(diào)。
using ReplyStringCb = function<void (ReplyType, const string& sReply)>;
CRedis::Get() 的回調(diào)就是 ReplyStringCb。
void CRedis::Set() 的回調(diào)只需知道成功或失敗,SetCb 定義為:
using SetCb = function<void (bool ok)>;
失敗時(shí)會(huì)有錯(cuò)誤信息,已統(tǒng)一打印日志,不再暴露出來(lái)。
SET 命令完整的參數(shù)列表還有其他參數(shù):
set key value [EX seconds] [PX milliseconds] [NX|XX]
因?yàn)槌S玫木?"set key value", 其他擴(kuò)展的命令需要使用通用的 command() 接口,
并需要讀取 redisReply.
使用 LuaIntf 導(dǎo)出 CRedis 到 Lua.
因?yàn)橹挥幸粋€(gè) CRedis, 所以導(dǎo)出為模塊 c_redis:
#include <LuaIntf/LuaIntf.h>
namespace {
void Set(const string& sKey, const string& sValue, const LuaRef& luaSetCb)
{
// Default is empty callback.
auto setCb = ToFunction<CRedis::SetCb>(luaSetCb);
GetRedis().Set(sKey, sValue, setCb);
}
void Get(const string& sKey, const LuaRef& luaReplyStringCb)
{
auto replyStringCb = ToFunction<CRedis::ReplyStringCb>(
luaReplyStringCb);
GetRedis().Get(sKey, replyStringCb);
}
} // namespace
void Bind(lua_State* L)
{
LuaBinding(L).beginModule("c_redis")
.addFunction("set", &Set)
.addFunction("get", &Get)
.endModule();
}
需要將 lua 的回調(diào)函數(shù)轉(zhuǎn)成 cpp 的回調(diào):
template <class Function>
Function ToFunction(const LuaIntf::LuaRef& luaFunction)
{
// Default is empty.
if (!luaFunction)
return Function(); // skip nil
if (luaFunction.isFunction())
return luaFunction.toValue<Function>(); // Todo: catch
LOG_WARN_TO("ToFunction", "Lua function expected, but got "
<< luaFunction.typeName());
return Function();
}
Lua 這樣調(diào)用:
c_redis.set("FOO", "1234")
c_redis.set("FOO", "1234", function(ok) print(ok) end)
c_redis.get("FOO", function(reply_type, reply)
assert("string" == type(reply))
if 0 == reply_type or 1 == reply_type then
print("FOO="..reply)
else
print("Error: "..reply)
end
end)
posted on 2017-01-05 18:42
金慶
閱讀(1003)
評(píng)論(0)
編輯
收藏
引用
所屬分類(lèi):
1. C/C++
、
2. 網(wǎng)游開(kāi)發(fā)
只有注冊(cè)用戶(hù)
登錄
后才能發(fā)表評(píng)論。
【推薦】100%開(kāi)源!大型工業(yè)跨平臺(tái)軟件C++源碼提供,建模,組態(tài)!
相關(guān)文章:
How are dtLinks created in NavMesh
C++ parameter passing rules
Naming Conventions for Accessors
Visual Studio 2019 Compiler Hangs
Fbx File Format Identifier
查找內(nèi)存錯(cuò)誤
std::thread 中的異常會(huì)丟失調(diào)用棧
用賦值代替 protobuf CopyFrom()
vs2017 linux 編譯輸出改成 vs 格式
為 LiteIDE 添加選中標(biāo)記
網(wǎng)站導(dǎo)航:
博客園
IT新聞
BlogJava
博問(wèn)
Chat2DB
管理
Powered by:
C++博客
Copyright © 金慶
国产成人久久精品激情
|
精品国产一区二区三区久久蜜臀
|
色婷婷噜噜久久国产精品12p
|
亚洲国产精品综合久久网络
|
久久精品人人做人人爽电影
|
国内精品久久久久伊人av
|
亚洲国产成人久久精品影视
|
亚洲精品tv久久久久
|
久久久久久久久久久久中文字幕
|
久久久久免费视频
|
久久男人AV资源网站
|
欧美精品久久久久久久自慰
|
日韩一区二区久久久久久
|
模特私拍国产精品久久
|
avtt天堂网久久精品
|
久久人人爽人人爽人人片AV东京热
|
久久久久久狠狠丁香
|
色综合久久天天综线观看
|
久久av无码专区亚洲av桃花岛
|
97久久国产露脸精品国产
|
精品久久久噜噜噜久久久
|
精品少妇人妻av无码久久
|
色偷偷88888欧美精品久久久
|
久久精品国产99久久久古代
|
亚洲欧美日韩久久精品第一区
|
99精品久久久久中文字幕
|
久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口
|
久久久婷婷五月亚洲97号色
|
韩国无遮挡三级久久
|
91精品国产色综久久
|
国产精品xxxx国产喷水亚洲国产精品无码久久一区
|
欧美成a人片免费看久久
|
久久午夜福利无码1000合集
|
香港aa三级久久三级
|
人妻精品久久久久中文字幕69
|
亚洲综合精品香蕉久久网97
|
伊人久久综合热线大杳蕉下载
|
97久久超碰国产精品2021
|
国内精品人妻无码久久久影院导航
|
国产L精品国产亚洲区久久
|
国产精品99久久精品爆乳
|