金慶的專(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 © 金慶
日产精品久久久久久久
|
2020久久精品国产免费
|
精品一久久香蕉国产线看播放
|
久久久久亚洲Av无码专
|
久久99精品久久久久久hb无码
|
天天久久狠狠色综合
|
香蕉久久影院
|
久久亚洲精品无码AV红樱桃
|
2022年国产精品久久久久
|
久久九九久精品国产
|
亚洲AV成人无码久久精品老人
|
国产精品对白刺激久久久
|
青青热久久国产久精品
|
99久久无码一区人妻a黑
|
国产三级观看久久
|
人妻少妇久久中文字幕
|
久久久不卡国产精品一区二区
|
久久精品aⅴ无码中文字字幕不卡
|
狠色狠色狠狠色综合久久
|
无码国内精品久久人妻麻豆按摩
|
麻豆久久久9性大片
|
97精品国产97久久久久久免费
|
亚洲精品白浆高清久久久久久
|
久久99国产精品久久
|
久久久久久精品无码人妻
|
国产午夜精品理论片久久
|
国产麻豆精品久久一二三
|
久久久亚洲精品蜜桃臀
|
久久精品国产亚洲麻豆
|
欧美熟妇另类久久久久久不卡
|
久久婷婷五月综合97色直播
|
国产亚州精品女人久久久久久
|
精品九九久久国内精品
|
91精品国产乱码久久久久久
|
中文字幕久久久久人妻
|
99蜜桃臀久久久欧美精品网站
|
久久精品国产色蜜蜜麻豆
|
一级做a爰片久久毛片免费陪
|
国产精品久久久福利
|
国产精品青草久久久久婷婷
|
久久99精品国产麻豆
|