RedisClient.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. #include "RedisClient.h"
  2. #include <QThread>
  3. #include <QTimer>
  4. //void Test()
  5. //{
  6. // struct st
  7. // {
  8. // int a;
  9. // int b;
  10. // char c;
  11. // int d;
  12. // };
  13. // st t;
  14. // t.a = 1;
  15. // t.b = 2;
  16. // t.c = 'a';
  17. // t.d = 4;
  18. // const char *v[3];
  19. // size_t vlen[3];
  20. // v[0] = "set";
  21. // vlen[0] = strlen("set");
  22. // v[1] = "st";
  23. // vlen[1] = strlen("st");
  24. // v[2] = (const char *)&t;
  25. // vlen[2] = sizeof(struct st);
  26. // redisReply *r = (redisReply *)redisCommandArgv(rc, sizeof(v) / sizeof(v[0]), v, vlen);
  27. // r = (redisReply *)redisCommand(rc, "get st");
  28. // if (!r) {
  29. // printf("empty reply\n");
  30. // exit(1);
  31. // }
  32. // st *t2 = (st*)(r->str);
  33. // qDebug()<< "st2" << t2->a << t2->b << t2->c << t2->d;
  34. //}
  35. void getCallback(redisAsyncContext *ctx, void *r, void *privdata){
  36. qDebug() << "getCallback called";
  37. redisReply *reply = static_cast<redisReply*>(r);
  38. if(reply == nullptr){
  39. qDebug() << "The reply is nullptr";
  40. return;
  41. }
  42. for(int i = 0; i < reply->elements; i++){
  43. qDebug() << "key: " << reply->element[i]->str;
  44. }
  45. if (QString(reply->element[0]->str) == "message") //收到订阅消息
  46. {
  47. QString ch = QString(reply->element[1]->str);
  48. if (ch == "DevCh")
  49. {
  50. qDebug()<<"devch...";
  51. // qDebug()<<"img:" << ++cnt;
  52. // QString js = QString(reply->element[2]->str);
  53. // QJsonObject jsonObj = QJsonDocument::fromJson(js.toLocal8Bit()).object(); //转成本地编码(utf-8), 中文正常
  54. // //quint32 type = jsonObj.value("type").toInt(); //toInt() 会丢数据
  55. // //qDebug()<<"type:" << type;
  56. // //QString base64Str = QString(reply->element[2]->str);
  57. // QString base64Str = jsonObj["img"].toString();
  58. // //qDebug()<<"str size:" << base64Str.size();
  59. // QPixmap baseimage;
  60. // baseimage.loadFromData(QByteArray::fromBase64(base64Str.toLatin1()));
  61. // QPixmap scaledPixmap = baseimage.scaled(500, 500, Qt::KeepAspectRatio); //设置图片大小并设置为按比例缩放
  62. // lab->setPixmap(scaledPixmap); //label放置图片并显示
  63. }
  64. else if (ch == "Alarm")
  65. {
  66. qDebug()<<"alarm...";
  67. }
  68. else if (ch == "Led")
  69. {
  70. qDebug()<<"led...";
  71. }
  72. }
  73. redisAsyncCommand(ctx, getCallback, nullptr, "blpop lTest 0");
  74. }
  75. void connectCallback(const redisAsyncContext *c, int status) {
  76. if (status != REDIS_OK) {
  77. qDebug("Error1: %s\n", c->errstr);
  78. //redisOk = false;
  79. return;
  80. }
  81. qDebug("Connected...\n");
  82. }
  83. void disconnectCallback(const redisAsyncContext *c, int status) {
  84. if (status != REDIS_OK) {
  85. qDebug("Error2: %s\n", c->errstr);
  86. //redisOk = false;
  87. return;
  88. }
  89. qDebug("Disconnected...\n");
  90. }
  91. RedisClient::RedisClient(QObject *parent) : QObject(parent)
  92. {
  93. redisOk = false;
  94. // conn();
  95. }
  96. RedisClient::~RedisClient()
  97. {
  98. delete rc;
  99. delete rac;
  100. }
  101. void RedisClient::conn()
  102. {
  103. if (!redisOk) //未连接
  104. {
  105. //同步连接
  106. rc = redisConnect(ip.toUtf8(), port);
  107. if(rc == nullptr || rc->err)
  108. {
  109. qDebug()<< "redis err:" << rc->errstr;
  110. }
  111. else
  112. {
  113. QString authCmd = "auth " + auth; //认证
  114. redisReply * reply = (redisReply*)redisCommand(rc, authCmd.toUtf8());
  115. //qDebug()<< "auth:" << reply->str;
  116. if (QString::compare(reply->str, "OK"))
  117. {
  118. qDebug() << "redis connect fail.";
  119. }
  120. else
  121. {
  122. redisOk = true;
  123. qDebug() << "redis connect successfully.";
  124. }
  125. }
  126. }
  127. else
  128. {
  129. //qDebug()<< "~ ";
  130. }
  131. }
  132. void RedisClient::start()
  133. {
  134. conn();
  135. //开启一个定时器, 每秒检测一次是否断开, 断开后自动连接redis服务器
  136. QTimer *redisTimer = new QTimer();
  137. connect(redisTimer, SIGNAL(timeout()), this, SLOT(conn()));
  138. redisTimer->start(1000);
  139. }
  140. bool RedisClient::hset(const QString& m, const QString& k, const QString& v)
  141. {
  142. //如果 field 是哈希表中的一个新建域,并且值设置成功,reply->integer为1
  143. //如果哈希表中域 field 已经存在且旧值已被新值覆盖,reply->integer为0
  144. //无法区别是否成功
  145. bool ret = false;
  146. redisReply * reply = (redisReply*)redisCommand(rc, QString("hset " + m + " " + k + " " + v).toStdString().c_str());
  147. if (rc->err)
  148. {
  149. redisOk = false;
  150. qDebug() << rc->errstr;
  151. }
  152. else
  153. {
  154. //qDebug() <<"type:" << reply->type << reply->integer; //type = 3
  155. ret = true;
  156. }
  157. return ret;
  158. }
  159. QString RedisClient::hget(const QString& m, const QString& k)
  160. {
  161. QString ret;
  162. redisReply * reply = (redisReply*)redisCommand(rc, QString("hget " + m + " " + k).toStdString().c_str());
  163. if (rc->err)
  164. {
  165. redisOk = false;
  166. qDebug() << rc->errstr;
  167. }
  168. else
  169. {
  170. //type:4表示不存在,type:1表示返回的为字符串
  171. //qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:1
  172. if (reply->len)
  173. {
  174. ret = QString(reply->str);
  175. }
  176. }
  177. return ret;
  178. }
  179. QStringList RedisClient::hkeys(const QString& k)
  180. {
  181. QStringList ret;
  182. redisReply *reply = (redisReply *)redisCommand(rc, QString("hkeys " + k).toStdString().c_str());
  183. if (rc->err)
  184. {
  185. redisOk = false;
  186. qDebug() << rc->errstr;
  187. }
  188. else if (reply->type == REDIS_REPLY_ARRAY)
  189. {
  190. // type:4表示不存在,type:1表示返回的为字符串
  191. // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:1
  192. for (size_t i = 0; i < reply->elements; i++)
  193. {
  194. // qDebug() << "key: " << i << reply->element[i]->str;
  195. ret.append(QString(reply->element[i]->str));
  196. }
  197. }
  198. return ret;
  199. }
  200. QStringList RedisClient::hvals(const QString& k)
  201. {
  202. QStringList ret;
  203. redisReply *reply = (redisReply *)redisCommand(rc, QString("hvals " + k).toStdString().c_str());
  204. if (rc->err)
  205. {
  206. redisOk = false;
  207. qDebug() << rc->errstr;
  208. }
  209. else if (reply->type == REDIS_REPLY_ARRAY)
  210. {
  211. // type:4表示不存在,type:1表示返回的为字符串
  212. // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:1
  213. for (size_t i = 0; i < reply->elements; i++)
  214. {
  215. // qDebug() << "key: " << i << reply->element[i]->str;
  216. ret.append(QString(reply->element[i]->str));
  217. }
  218. }
  219. return ret;
  220. }
  221. QHash<QString, QString> RedisClient::hgetall(const QString& k)
  222. {
  223. QHash<QString, QString> ret;
  224. redisReply *reply = (redisReply *)redisCommand(rc, QString("hgetall " + k).toStdString().c_str());
  225. if (rc->err)
  226. {
  227. redisOk = false;
  228. qDebug() << rc->errstr;
  229. }
  230. else if (reply->type == REDIS_REPLY_ARRAY)
  231. {
  232. // type:4表示不存在,type:1表示返回的为字符串
  233. // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:1
  234. for (size_t i = 0; i < reply->elements; i += 2)
  235. {
  236. // qDebug() << "key: " << i << reply->element[i]->str;
  237. ret.insert(QString(reply->element[i]->str), QString(reply->element[i + 1]->str));
  238. }
  239. }
  240. return ret;
  241. }
  242. //向队列尾(右)部加入字符串数据
  243. bool RedisClient::rpush(const QString& lData, const QString& js)
  244. {
  245. bool ret = false;
  246. redisReply * reply = (redisReply*)redisCommand(rc, QString("rpush " + lData + " " + js).toStdString().c_str());
  247. if (rc->err)
  248. {
  249. redisOk = false;
  250. qDebug() << rc->errstr;
  251. }
  252. else
  253. {
  254. //qDebug() <<"type:" << reply->type << reply->integer; //type = 3
  255. //reply->integer为队列的个数,理论应该大于0
  256. if (reply->integer)
  257. {
  258. ret = true;
  259. }
  260. }
  261. return ret;
  262. }
  263. //向队列尾(右)部加入二进制数据
  264. bool RedisClient::rpushb(const QString& lData, const QByteArray& ba)
  265. {
  266. bool ret = false;
  267. const char *arg[3]; //3个参数(cmd, k, v)
  268. size_t vlen[3]; //3个参数长度
  269. arg[0] = "rpush";
  270. vlen[0] = strlen("rpush");
  271. arg[1] = lData.toStdString().c_str();
  272. vlen[1] = lData.size();
  273. arg[2] = (const char *)ba.data();
  274. vlen[2] = ba.size();
  275. redisReply *reply = (redisReply *)redisCommandArgv(rc, sizeof(arg) / sizeof(arg[0]), arg, vlen);
  276. //redisReply * reply = (redisReply*)redisCommand(rc, QString("rpush " + lData + " " + js).toStdString().c_str());
  277. if (rc->err)
  278. {
  279. redisOk = false;
  280. qDebug() << rc->errstr;
  281. }
  282. else
  283. {
  284. //qDebug() <<"type:" << reply->type << reply->integer; //type = 3
  285. //reply->integer为队列的个数,理论应该大于0
  286. if (reply->integer)
  287. {
  288. ret = true;
  289. }
  290. }
  291. return ret;
  292. }
  293. QString RedisClient::lpop(const QString& lData)
  294. {
  295. QString ret;
  296. redisReply * reply = (redisReply*)redisCommand(rc, QString("lpop " + lData).toStdString().c_str());
  297. if (rc->err)
  298. {
  299. redisOk = false;
  300. qDebug() << rc->errstr;
  301. }
  302. else if (reply->len)
  303. {
  304. ret = QString(reply->str);
  305. }
  306. return ret;
  307. }
  308. //阻塞从队列头部获取最早数据
  309. bool RedisClient::blpop(const QString& lData, redisCallbackFn *fn)
  310. {
  311. if (rac == nullptr)
  312. {
  313. //异步连接
  314. rac = redisAsyncConnect(ip.toUtf8(), port);
  315. if(rac->err)
  316. {
  317. qDebug()<< "error: " << rac->errstr;
  318. redisAsyncFree(rac);
  319. }
  320. else
  321. {
  322. adapter.setContext(rac);
  323. redisAsyncSetConnectCallback(rac, connectCallback);
  324. redisAsyncSetDisconnectCallback(rac, disconnectCallback);
  325. QString authCmd = "auth " + auth; //认证
  326. redisAsyncCommand(rac, nullptr, nullptr, authCmd.toUtf8());
  327. qDebug()<< "redis ok.";
  328. redisOk = true;
  329. }
  330. }
  331. if (rac && redisOk)
  332. {
  333. redisAsyncCommand(rac, fn, nullptr, ("blpop " + lData + " 0").toStdString().c_str());
  334. return true;
  335. }
  336. else
  337. {
  338. return false;
  339. }
  340. }
  341. //同步阻塞一定时间返回数据
  342. QString RedisClient::blpop(const QString& lData, quint32 timeout)
  343. {
  344. //最小为1,防止0时永久阻塞
  345. if (timeout < 1)
  346. {
  347. timeout = 1;
  348. }
  349. QString ret;
  350. redisReply * reply = (redisReply*)redisCommand(rc, QString("blpop " + lData + " " + QString::number(timeout)).toStdString().c_str());
  351. // for(int i = 0; i < reply->elements; i++){
  352. // qDebug() << "key: " << reply->element[i]->str;
  353. // }
  354. if (rc->err)
  355. {
  356. redisOk = false;
  357. qDebug() << rc->errstr;
  358. }
  359. else if (reply->elements > 1)
  360. {
  361. ret = QString(reply->element[1]->str);
  362. }
  363. return ret;
  364. }
  365. bool RedisClient::set(const QString& k, const QString& v)
  366. {
  367. bool ret = false;
  368. redisReply * reply = (redisReply*)redisCommand(rc, QString("set " + k + " " + v).toStdString().c_str()); //支持空格
  369. if (rc->err)
  370. {
  371. redisOk = false;
  372. qDebug() << rc->errstr;
  373. }
  374. else
  375. {
  376. //qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:5 str:OK len:2
  377. if (reply->type == 6)
  378. {
  379. qDebug()<<"err:" << v;
  380. }
  381. //返回OK为成功,长度2为str长度
  382. ret = true;
  383. }
  384. return ret;
  385. }
  386. bool RedisClient::setb(const QString& k, const QByteArray &v)
  387. {
  388. bool ret = false;
  389. const char *arg[3]; //3个参数(cmd, k, v)
  390. size_t vlen[3]; //3个参数长度
  391. arg[0] = "set";
  392. vlen[0] = strlen("set");
  393. arg[1] = k.toStdString().c_str();
  394. vlen[1] = k.size();
  395. arg[2] = (const char *)v.data();
  396. vlen[2] = v.size();
  397. redisReply *reply = (redisReply *)redisCommandArgv(rc, sizeof(arg) / sizeof(arg[0]), arg, vlen);
  398. if (rc->err)
  399. {
  400. redisOk = false;
  401. qDebug() << rc->errstr;
  402. }
  403. else
  404. {
  405. //qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:5 str:OK len:2
  406. if (reply->type == 6)
  407. {
  408. qDebug()<<"err:" << v;
  409. }
  410. //返回OK为成功,长度2为str长度
  411. ret = true;
  412. }
  413. return ret;
  414. }
  415. QString RedisClient::get(const QString& k)
  416. {
  417. QString ret;
  418. redisReply * reply = (redisReply*)redisCommand(rc, QString("get " + k).toStdString().c_str());
  419. if (rc->err)
  420. {
  421. redisOk = false;
  422. qDebug() << rc->errstr;
  423. }
  424. else if (reply->len)
  425. {
  426. ret = QString(reply->str);
  427. }
  428. return ret;
  429. }
  430. QByteArray RedisClient::getb(const QString& k)
  431. {
  432. QByteArray ret;
  433. redisReply * reply = (redisReply*)redisCommand(rc, QString("get " + k).toStdString().c_str());
  434. if (rc->err)
  435. {
  436. redisOk = false;
  437. qDebug() << rc->errstr;
  438. }
  439. else if (reply->len)
  440. {
  441. ret = QByteArray(reply->str, reply->len); //加上长度,保证二进制安全
  442. //qDebug()<< reply->len << ret.size();
  443. }
  444. return ret;
  445. }
  446. bool RedisClient::expire(const QString& k,int sec)
  447. {
  448. bool ret = false;
  449. redisReply * reply = (redisReply*)redisCommand(rc, QString("expire " + k + " " + QString::number(sec, 10)).toStdString().c_str());
  450. if (rc->err)
  451. {
  452. redisOk = false;
  453. qDebug() << rc->errstr;
  454. }
  455. else
  456. {
  457. //qDebug() <<"type:" << reply->type << reply->integer; //type = 3
  458. //K不存在为0,存在为1
  459. if (reply->integer)
  460. {
  461. ret = true;
  462. }
  463. }
  464. return ret;
  465. }
  466. bool RedisClient::publish(const QString& ch, const QString& js)
  467. {
  468. bool ret = false;
  469. QString pub = QString("publish " + ch + " " + js);
  470. redisReply * reply = (redisReply*)redisCommand(rc, pub.toStdString().c_str());
  471. qDebug() << __FUNCTION__ << pub;
  472. if (rc->err)
  473. {
  474. redisOk = false;
  475. qDebug() << rc->errstr;
  476. }
  477. else
  478. {
  479. //qDebug() <<"type:" << reply->type << reply->integer; //type:3, integer:2
  480. //integer为2,不懂什么意思,这个用于实时,无需判断是否成功,连接正常即可
  481. ret = true;
  482. }
  483. return ret;
  484. }
  485. bool RedisClient::publishb(const QString& ch,const QByteArray& ba)
  486. {
  487. bool ret = false;
  488. const char *arg[3]; //3个参数(cmd, k, v)
  489. size_t vlen[3]; //3个参数长度
  490. arg[0] = "publish";
  491. vlen[0] = strlen("publish");
  492. arg[1] = ch.toStdString().c_str();
  493. vlen[1] = ch.size();
  494. arg[2] = (const char *)ba.data();
  495. vlen[2] = ba.size();
  496. redisReply *reply = (redisReply *)redisCommandArgv(rc, sizeof(arg) / sizeof(arg[0]), arg, vlen);
  497. //redisReply * reply = (redisReply*)redisCommand(rc, QString("publish " + ch + " " + js).toStdString().c_str());
  498. if (rc->err)
  499. {
  500. redisOk = false;
  501. qDebug() << rc->errstr;
  502. }
  503. else
  504. {
  505. qDebug() <<"type:" << reply->type << reply->integer; //type:3, integer:2
  506. //integer为2,不懂什么意思,这个用于实时,无需判断是否成功,连接正常即可
  507. ret = true;
  508. }
  509. return ret;
  510. }
  511. void RedisClient::subscribe(const QString& ch, redisCallbackFn *fn, void* data)
  512. {
  513. if (rac == nullptr)
  514. {
  515. //异步连接
  516. rac = redisAsyncConnect(ip.toUtf8(), port);
  517. if(rac->err)
  518. {
  519. qDebug()<< "error: " << rac->errstr;
  520. redisAsyncFree(rac);
  521. }
  522. else
  523. {
  524. adapter.setContext(rac);
  525. redisAsyncSetConnectCallback(rac, connectCallback);
  526. redisAsyncSetDisconnectCallback(rac, disconnectCallback);
  527. QString authCmd = "auth " + auth; //认证
  528. redisAsyncCommand(rac, nullptr, data, authCmd.toUtf8());
  529. qDebug()<< "redis ok.";
  530. redisOk = true;
  531. }
  532. }
  533. if (rac && redisOk)
  534. {
  535. redisAsyncCommand(rac, fn, data, QString("subscribe " + ch).toStdString().c_str());
  536. }
  537. }
  538. void RedisClient::psubscribe(const QString& ch, redisCallbackFn *fn, void* data)
  539. {
  540. if (rac == nullptr)
  541. {
  542. //异步连接
  543. rac = redisAsyncConnect(ip.toUtf8(), port);
  544. if(rac->err)
  545. {
  546. qDebug()<< "error: " << rac->errstr;
  547. redisAsyncFree(rac);
  548. }
  549. else
  550. {
  551. adapter.setContext(rac);
  552. redisAsyncSetConnectCallback(rac, connectCallback);
  553. redisAsyncSetDisconnectCallback(rac, disconnectCallback);
  554. QString authCmd = "auth " + auth; //认证
  555. redisAsyncCommand(rac, nullptr, data, authCmd.toUtf8());
  556. qDebug()<< "redis ok.";
  557. redisOk = true;
  558. }
  559. }
  560. if (rac && redisOk)
  561. {
  562. redisAsyncCommand(rac, fn, data, QString("psubscribe " + ch).toStdString().c_str());
  563. }
  564. }
  565. void RedisClient::Setup(const QString& addr, uint _port,const QString&password)
  566. {
  567. ip = addr;
  568. port = _port;
  569. auth = password;
  570. redisOk = false;
  571. conn();
  572. }