├── .gitattributes ├── .gitignore ├── LICENSE ├── ReadMe.md ├── RedisClient.sln └── RedisClient ├── RedisClient.cpp ├── RedisClient.h ├── RedisClient.vcxproj ├── RedisClient.vcxproj.filters ├── RedisExpress.cpp ├── RedisExpress.h ├── RedisMsg.cpp ├── RedisMsg.h └── main.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 LZkila 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | ## Redis客户端 2 | 可以向Redis服务器发送Redis相关的指令,在qt下的封装 -------------------------------------------------------------------------------- /RedisClient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2027 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RedisClient", "RedisClient\RedisClient.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.ActiveCfg = Debug|x64 15 | {B12702AD-ABFB-343A-A199-8E24837244A3}.Debug|x64.Build.0 = Debug|x64 16 | {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.ActiveCfg = Release|x64 17 | {B12702AD-ABFB-343A-A199-8E24837244A3}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {F9470EF4-B6D7-44F8-BEEB-5A291B77ABA0} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /RedisClient/RedisClient.cpp: -------------------------------------------------------------------------------- 1 | #include "RedisClient.h" 2 | #include 3 | #include 4 | 5 | #include "RedisExpress.h" 6 | 7 | RedisClient::RedisClient(QObject *parent) 8 | : QObject(parent) 9 | { 10 | init(); 11 | } 12 | 13 | RedisClient::RedisClient(const QString &hostAddress, int port, QObject *parent) 14 | : QObject(parent) 15 | { 16 | init(); 17 | setHostAddress(hostAddress); 18 | setPort(port); 19 | } 20 | 21 | QString RedisClient::getHostAddress() 22 | { 23 | return _express->getHostAddress(); 24 | } 25 | 26 | void RedisClient::setHostAddress(const QString &hostAddress) 27 | { 28 | Q_ASSERT(_express != NULL); 29 | _express->setHostAddress(hostAddress); 30 | } 31 | 32 | void RedisClient::setPort(int port) 33 | { 34 | Q_ASSERT(_express != NULL); 35 | _express->setPort(port); 36 | } 37 | 38 | int RedisClient::getPort() 39 | { 40 | return _express->getPort(); 41 | } 42 | 43 | bool RedisClient::isOpen() 44 | { 45 | return _express->isOpen(); 46 | } 47 | 48 | void RedisClient::open() 49 | { 50 | _express->open(); 51 | } 52 | 53 | void RedisClient::open(const QString &hostAddress, int port) 54 | { 55 | _express->open(hostAddress, port); 56 | } 57 | 58 | void RedisClient::close() 59 | { 60 | _express->close(); 61 | } 62 | 63 | RedisMsg RedisClient::command(const QString & str) 64 | { 65 | _express->write(str); 66 | 67 | QEventLoop loop; 68 | connect(_express, &RedisExpress::sigReply, [&loop](const QStringList &res) 69 | { 70 | loop.quit(); 71 | }); 72 | 73 | QTimer t; 74 | t.setInterval(_nMaxTimeOfCmd); 75 | t.setSingleShot(true); 76 | bool bTimeout = false; 77 | connect(&t, &QTimer::timeout, [&loop, &bTimeout]() // 超时处理 78 | { 79 | loop.quit(); 80 | bTimeout = true; 81 | }); 82 | t.start(); 83 | 84 | loop.exec(); 85 | 86 | if (bTimeout) 87 | return RedisMsg(); 88 | 89 | return _msg; 90 | } 91 | 92 | void RedisClient::publish(const QString & channel, const QString & message) 93 | { 94 | QString cmd; 95 | cmd.append("PUBLISH "); 96 | cmd.append(channel); 97 | cmd.append(" "); 98 | cmd.append(message); 99 | 100 | _express->write(cmd); 101 | } 102 | 103 | void RedisClient::subscribe(const QString & channel) 104 | { 105 | QString cmd; 106 | cmd.append("SUBSCRIBE "); 107 | cmd.append(channel); 108 | 109 | _express->write(cmd); 110 | } 111 | 112 | void RedisClient::unsubscribe(const QString & channel) 113 | { 114 | QString cmd; 115 | cmd.append("UNSUBSCRIBE "); 116 | cmd.append(channel); 117 | 118 | _express->write(cmd); 119 | } 120 | 121 | void RedisClient::psubscribe(const QString & pattern) 122 | { 123 | QString cmd; 124 | cmd.append("PSUBSCRIBE "); 125 | cmd.append(pattern); 126 | 127 | _express->write(cmd); 128 | } 129 | 130 | void RedisClient::punsubscribe(const QString & pattern) 131 | { 132 | QString cmd; 133 | cmd.append("PUNSUBSCRIBE "); 134 | cmd.append(pattern); 135 | 136 | _express->write(cmd); 137 | } 138 | 139 | int RedisClient::append(const QString & key, const QString & value) 140 | { 141 | QString cmd("APPEND "); 142 | cmd.append(key); 143 | cmd.append(" "); 144 | cmd.append(value); 145 | 146 | auto reply = command(cmd); 147 | 148 | return reply.value.toInt(); 149 | } 150 | 151 | bool RedisClient::auth(const QString & password) 152 | { 153 | QString cmd("AUTH "); 154 | cmd.append(password); 155 | 156 | auto reply = command(cmd); 157 | if (reply.value.toString() == "OK") 158 | return true; 159 | return false; 160 | } 161 | 162 | QStringList RedisClient::blpop(const QString & key, int timeout) 163 | { 164 | QString cmd("BLPOP "); 165 | cmd.append(key); 166 | cmd.append(" "); 167 | cmd.append(QString::number(timeout)); 168 | 169 | auto reply = command(cmd); 170 | return reply.value.toStringList(); 171 | } 172 | 173 | QStringList RedisClient::brpop(const QString & key, int timeout) 174 | { 175 | QString cmd("BRPOP "); 176 | cmd.append(key); 177 | cmd.append(" "); 178 | cmd.append(QString::number(timeout)); 179 | 180 | auto reply = command(cmd); 181 | return reply.value.toStringList(); 182 | } 183 | 184 | QStringList RedisClient::brpoplpush(const QString & source, const QString & destination, int timeout) 185 | { 186 | QString cmd("BRPOPLPUSH "); 187 | cmd.append(source); 188 | cmd.append(" "); 189 | cmd.append(destination); 190 | cmd.append(" "); 191 | cmd.append(QString::number(timeout)); 192 | 193 | auto reply = command(cmd); 194 | return reply.value.toStringList(); 195 | } 196 | 197 | int RedisClient::decr(const QString & key) 198 | { 199 | QString cmd("DECR "); 200 | cmd.append(key); 201 | 202 | auto reply = command(cmd); 203 | return reply.value.toInt(); 204 | } 205 | 206 | int RedisClient::decrby(const QString & key, int interval) 207 | { 208 | QString cmd("DECRBY "); 209 | cmd.append(key); 210 | cmd.append(" "); 211 | cmd.append(QString::number(interval)); 212 | 213 | auto reply = command(cmd); 214 | return reply.value.toInt(); 215 | } 216 | 217 | int RedisClient::del(const QString & key) 218 | { 219 | QString cmd("DEL "); 220 | cmd.append(key); 221 | 222 | auto reply = command(cmd); 223 | return reply.value.toInt(); 224 | } 225 | 226 | QString RedisClient::dump(const QString & key) 227 | { 228 | QString cmd("DUMP "); 229 | cmd.append(key); 230 | 231 | auto reply = command(cmd); 232 | return reply.value.toString(); 233 | } 234 | 235 | bool RedisClient::exists(const QString & key) 236 | { 237 | QString cmd("EXISTS "); 238 | cmd.append(key); 239 | 240 | auto reply = command(cmd); 241 | return reply.value.toBool(); 242 | } 243 | 244 | bool RedisClient::expire(const QString & key, int seconds) 245 | { 246 | QString cmd("EXPIRE "); 247 | cmd.append(key); 248 | cmd.append(" "); 249 | cmd.append(QString::number(seconds)); 250 | 251 | auto reply = command(cmd); 252 | return reply.value.toBool(); 253 | } 254 | 255 | bool RedisClient::expireat(const QString & key, int timestamp) 256 | { 257 | QString cmd("EXPIREAT "); 258 | cmd.append(key); 259 | cmd.append(" "); 260 | cmd.append(QString::number(timestamp)); 261 | 262 | auto reply = command(cmd); 263 | return reply.value.toBool(); 264 | } 265 | 266 | QVariant RedisClient::eval(const QString & script, int numkeys, const QString & keys, const QString & arguments) 267 | { 268 | QString cmd("EVAL "); 269 | cmd.append(script); 270 | cmd.append(" "); 271 | cmd.append(QString::number(numkeys)); 272 | cmd.append(" "); 273 | cmd.append(keys); 274 | cmd.append(" "); 275 | cmd.append(arguments); 276 | 277 | auto reply = command(cmd); 278 | return reply.value; 279 | } 280 | 281 | QVariant RedisClient::evalsha(const QString & sha1, int numkeys, const QString & keys, const QString & arguments) 282 | { 283 | QString cmd("EVALSHA "); 284 | cmd.append(sha1); 285 | cmd.append(" "); 286 | cmd.append(QString::number(numkeys)); 287 | cmd.append(" "); 288 | cmd.append(keys); 289 | cmd.append(" "); 290 | cmd.append(arguments); 291 | 292 | auto reply = command(cmd); 293 | return reply.value; 294 | } 295 | 296 | QString RedisClient::get(const QString & key) 297 | { 298 | QString cmd("GET "); 299 | cmd.append(key); 300 | 301 | auto reply = command(cmd); 302 | return reply.value.toString(); 303 | } 304 | 305 | QString RedisClient::getrange(const QString & key, int start, int stop) 306 | { 307 | QString cmd("GETRANGE "); 308 | cmd.append(key); 309 | cmd.append(" "); 310 | cmd.append(QString::number(start)); 311 | cmd.append(" "); 312 | cmd.append(QString::number(stop)); 313 | 314 | auto reply = command(cmd); 315 | return reply.value.toString(); 316 | } 317 | 318 | int RedisClient::hdel(const QString & key, const QString & field) 319 | { 320 | QString cmd("HDEL "); 321 | cmd.append(key); 322 | cmd.append(" "); 323 | cmd.append(field); 324 | 325 | auto reply = command(cmd); 326 | return reply.value.toInt(); 327 | } 328 | 329 | bool RedisClient::hexists(const QString & key, const QString & field) 330 | { 331 | QString cmd("HEXISTS "); 332 | cmd.append(key); 333 | cmd.append(" "); 334 | cmd.append(field); 335 | 336 | auto reply = command(cmd); 337 | return reply.value.toBool(); 338 | } 339 | 340 | QString RedisClient::hget(const QString & key, const QString & field) 341 | { 342 | QString cmd("HGET "); 343 | cmd.append(key); 344 | cmd.append(" "); 345 | cmd.append(field); 346 | 347 | auto reply = command(cmd); 348 | return reply.value.toString(); 349 | } 350 | 351 | QMap RedisClient::hgetall(const QString & key) 352 | { 353 | QString cmd("HGETALL "); 354 | cmd.append(key); 355 | 356 | auto reply = command(cmd); 357 | 358 | QMap keypairs; 359 | QStringList list = reply.value.toStringList(); 360 | 361 | for (int i = 0; i map) 429 | { 430 | QString cmd("HMSET "); 431 | cmd.append(key); 432 | 433 | QMapIterator i(map); 434 | while (i.hasNext()) 435 | { 436 | i.next(); 437 | cmd.append(" "); 438 | cmd.append(i.key()); 439 | cmd.append(" "); 440 | cmd.append(i.value().toString()); 441 | 442 | } 443 | 444 | auto reply = command(cmd); 445 | if (reply.value.toString() == "OK") 446 | return true; 447 | 448 | return false; 449 | } 450 | 451 | bool RedisClient::hset(const QString & key, const QString & field, const QString & value) 452 | { 453 | QString cmd("HSET "); 454 | cmd.append(key); 455 | cmd.append(" "); 456 | cmd.append(field); 457 | cmd.append(" "); 458 | cmd.append(value); 459 | 460 | auto reply = command(cmd); 461 | return reply.value.toBool(); 462 | } 463 | 464 | bool RedisClient::hsetnx(const QString & key, const QString & field, const QString & value) 465 | { 466 | QString cmd("HSETNX "); 467 | cmd.append(key); 468 | cmd.append(" "); 469 | cmd.append(field); 470 | cmd.append(" "); 471 | cmd.append(value); 472 | 473 | auto reply = command(cmd); 474 | return reply.value.toBool(); 475 | } 476 | 477 | QStringList RedisClient::hvals(const QString & key) 478 | { 479 | QString cmd("HVALS "); 480 | cmd.append(key); 481 | 482 | auto reply = command(cmd); 483 | return reply.value.toStringList(); 484 | } 485 | 486 | int RedisClient::incr(const QString & key) 487 | { 488 | QString cmd("INCR "); 489 | cmd.append(key); 490 | 491 | auto reply = command(cmd); 492 | return reply.value.toInt(); 493 | } 494 | 495 | int RedisClient::incrby(const QString & key, int interval) 496 | { 497 | QString cmd("INCRBY "); 498 | cmd.append(key); 499 | cmd.append(" "); 500 | cmd.append(QString::number(interval)); 501 | 502 | auto reply = command(cmd); 503 | return reply.value.toInt(); 504 | } 505 | 506 | QStringList RedisClient::keys(const QString & pattern) 507 | { 508 | QString cmd("KEYS "); 509 | cmd.append(pattern); 510 | 511 | auto reply = command(cmd); 512 | return reply.value.toStringList(); 513 | } 514 | 515 | int RedisClient::lindex(const QString & key, int index) 516 | { 517 | QString cmd("LINDEX "); 518 | cmd.append(key); 519 | cmd.append(" "); 520 | cmd.append(QString::number(index)); 521 | 522 | auto reply = command(cmd); 523 | return reply.value.toInt(); 524 | } 525 | 526 | int RedisClient::linsert(const QString & key, const QString & position, const QString & pivot, const QString & value) 527 | { 528 | QString cmd("LINSERT "); 529 | cmd.append(key); 530 | cmd.append(" "); 531 | cmd.append(position); 532 | cmd.append(" "); 533 | cmd.append(pivot); 534 | cmd.append(" "); 535 | cmd.append(value); 536 | 537 | auto reply = command(cmd); 538 | return reply.value.toInt(); 539 | } 540 | 541 | int RedisClient::llen(const QString & key) 542 | { 543 | QString cmd("LLEN "); 544 | cmd.append(key); 545 | 546 | auto reply = command(cmd); 547 | return reply.value.toInt(); 548 | } 549 | 550 | QString RedisClient::lpop(const QString & key) 551 | { 552 | QString cmd("LPOP "); 553 | cmd.append(key); 554 | 555 | auto reply = command(cmd); 556 | return reply.value.toString(); 557 | } 558 | 559 | int RedisClient::lpush(const QString & key, const QString & value) 560 | { 561 | QString cmd("LPUSH "); 562 | cmd.append(key); 563 | cmd.append(" "); 564 | cmd.append(value); 565 | 566 | auto reply = command(cmd); 567 | return reply.value.toInt(); 568 | } 569 | 570 | int RedisClient::lpushx(const QString & key, const QString & value) 571 | { 572 | QString cmd("LPUSHX "); 573 | cmd.append(key); 574 | cmd.append(" "); 575 | cmd.append(value); 576 | 577 | auto reply = command(cmd); 578 | return reply.value.toInt(); 579 | } 580 | 581 | QStringList RedisClient::lrange(const QString & key, int start, int stop) 582 | { 583 | QString cmd("LRANGE "); 584 | cmd.append(key); 585 | cmd.append(" "); 586 | cmd.append(QString::number(start)); 587 | cmd.append(" "); 588 | cmd.append(QString::number(stop)); 589 | 590 | auto reply = command(cmd); 591 | return reply.value.toStringList(); 592 | } 593 | 594 | int RedisClient::lrem(const QString & key, int count, const QString & value) 595 | { 596 | QString cmd("LREM "); 597 | cmd.append(key); 598 | cmd.append(" "); 599 | cmd.append(QString::number(count)); 600 | cmd.append(" "); 601 | cmd.append(value); 602 | 603 | auto reply = command(cmd); 604 | return reply.value.toInt(); 605 | } 606 | 607 | int RedisClient::lset(const QString & key, int index, const QString & value) 608 | { 609 | QString cmd("LSET "); 610 | cmd.append(key); 611 | cmd.append(" "); 612 | cmd.append(QString::number(index)); 613 | cmd.append(" "); 614 | cmd.append(value); 615 | 616 | auto reply = command(cmd); 617 | return reply.value.toInt(); 618 | } 619 | 620 | bool RedisClient::ltrim(const QString & key, int start, int stop) 621 | { 622 | QString cmd("LTRIM "); 623 | cmd.append(key); 624 | cmd.append(" "); 625 | cmd.append(QString::number(start)); 626 | cmd.append(" "); 627 | cmd.append(QString::number(stop)); 628 | 629 | auto reply = command(cmd); 630 | 631 | if (reply.value.toString() == "OK") 632 | return true; 633 | return false; 634 | } 635 | 636 | QStringList RedisClient::mget(const QString & key) 637 | { 638 | QString cmd("MGET "); 639 | cmd.append(key); 640 | 641 | auto reply = command(cmd); 642 | return reply.value.toStringList(); 643 | } 644 | 645 | bool RedisClient::migrate(const QString & host, int port, const QString & key, int database, int timeout) 646 | { 647 | QString cmd("MIGRATE "); 648 | cmd.append(host); 649 | cmd.append(" "); 650 | cmd.append(QString::number(port)); 651 | cmd.append(" "); 652 | cmd.append(key); 653 | cmd.append(" "); 654 | cmd.append(QString::number(database)); 655 | cmd.append(" "); 656 | cmd.append(QString::number(timeout)); 657 | 658 | auto reply = command(cmd); 659 | 660 | if (reply.value.toString() == "OK") 661 | return true; 662 | return false; 663 | } 664 | 665 | bool RedisClient::move(const QString & key, int database) 666 | { 667 | QString cmd("MOVE "); 668 | cmd.append(key); 669 | cmd.append(" "); 670 | cmd.append(QString::number(database)); 671 | 672 | auto reply = command(cmd); 673 | return reply.value.toBool(); 674 | } 675 | 676 | bool RedisClient::mset(QMap map) 677 | { 678 | QString cmd("MSET"); 679 | 680 | QMapIterator i(map); 681 | while (i.hasNext()) 682 | { 683 | i.next(); 684 | cmd.append(" "); 685 | cmd.append(i.key()); 686 | cmd.append(" "); 687 | cmd.append(i.value().toString()); 688 | 689 | } 690 | 691 | auto reply = command(cmd); 692 | 693 | if (reply.value.toString() == "OK") 694 | return true; 695 | return false; 696 | } 697 | 698 | QVariant RedisClient::object(const QString & subcommand, const QString & arguments) 699 | { 700 | QString cmd("OBJECT "); 701 | cmd.append(subcommand); 702 | cmd.append(" "); 703 | cmd.append(arguments); 704 | 705 | auto reply = command(cmd); 706 | return reply.value; 707 | } 708 | 709 | bool RedisClient::persist(const QString & key) 710 | { 711 | QString cmd("PERSIST "); 712 | cmd.append(key); 713 | 714 | auto reply = command(cmd); 715 | return reply.value.toBool(); 716 | } 717 | 718 | bool RedisClient::pexpire(const QString & key, int mseconds) 719 | { 720 | QString cmd("PEXPIRE "); 721 | cmd.append(key); 722 | cmd.append(" "); 723 | cmd.append(QString::number(mseconds)); 724 | 725 | auto reply = command(cmd); 726 | return reply.value.toBool(); 727 | } 728 | 729 | bool RedisClient::pexpireat(const QString & key, int mstimestamp) 730 | { 731 | QString cmd("PEXPIREAT "); 732 | cmd.append(key); 733 | cmd.append(" "); 734 | cmd.append(QString::number(mstimestamp)); 735 | 736 | auto reply = command(cmd); 737 | return reply.value.toBool(); 738 | } 739 | 740 | int RedisClient::pttl(const QString & key) 741 | { 742 | QString cmd("PTTL "); 743 | cmd.append(key); 744 | 745 | auto reply = command(cmd); 746 | return reply.value.toInt(); 747 | } 748 | 749 | bool RedisClient::rename(const QString & key, const QString & newkey) 750 | { 751 | QString cmd("RENAME "); 752 | cmd.append(key); 753 | cmd.append(" "); 754 | cmd.append(newkey); 755 | 756 | auto reply = command(cmd); 757 | 758 | if (reply.value.toString() == "OK") 759 | return true; 760 | return false; 761 | } 762 | 763 | bool RedisClient::renamex(const QString & key, const QString & newkey) 764 | { 765 | QString cmd("RENAMEX "); 766 | cmd.append(key); 767 | cmd.append(" "); 768 | cmd.append(newkey); 769 | 770 | auto reply = command(cmd); 771 | 772 | if (reply.value.toString() == "OK") 773 | return true; 774 | return false; 775 | } 776 | 777 | bool RedisClient::restore(const QString & key, int ttl, const QString & value) 778 | { 779 | QString cmd("RESTORE "); 780 | cmd.append(key); 781 | cmd.append(" "); 782 | cmd.append(QString::number(ttl)); 783 | cmd.append(" "); 784 | cmd.append(value); 785 | 786 | auto reply = command(cmd); 787 | 788 | if (reply.value.toString() == "OK") 789 | return true; 790 | return false; 791 | } 792 | 793 | QString RedisClient::rpop(const QString & key) 794 | { 795 | QString cmd("RPOP "); 796 | cmd.append(key); 797 | 798 | auto reply = command(cmd); 799 | return reply.value.toString(); 800 | } 801 | 802 | QString RedisClient::rpoplpush(const QString & source, const QString & destination) 803 | { 804 | QString cmd("RPOPLPUSH "); 805 | cmd.append(source); 806 | cmd.append(" "); 807 | cmd.append(destination); 808 | 809 | auto reply = command(cmd); 810 | return reply.value.toString(); 811 | } 812 | 813 | int RedisClient::rpush(const QString & key, const QString & value) 814 | { 815 | QString cmd("RPUSH "); 816 | cmd.append(key); 817 | cmd.append(" "); 818 | cmd.append(value); 819 | 820 | auto reply = command(cmd); 821 | return reply.value.toInt(); 822 | } 823 | 824 | int RedisClient::rpushx(const QString & key, const QString & value) 825 | { 826 | QString cmd("RPUSHX "); 827 | cmd.append(key); 828 | cmd.append(" "); 829 | cmd.append(value); 830 | 831 | auto reply = command(cmd); 832 | return reply.value.toInt(); 833 | } 834 | 835 | bool RedisClient::sadd(const QString & key, const QString & member) 836 | { 837 | QString cmd("SADD "); 838 | cmd.append(key); 839 | cmd.append(" "); 840 | cmd.append(member); 841 | 842 | auto reply = command(cmd); 843 | return reply.value.toBool(); 844 | } 845 | 846 | int RedisClient::scard(const QString & key) 847 | { 848 | QString cmd("SCARD "); 849 | cmd.append(key); 850 | 851 | auto reply = command(cmd); 852 | return reply.value.toInt(); 853 | } 854 | 855 | QStringList RedisClient::scriptexists(const QString & script) 856 | { 857 | QString cmd("SCRIPT EXISTS "); 858 | cmd.append(script); 859 | 860 | auto reply = command(cmd); 861 | return reply.value.toStringList(); 862 | } 863 | 864 | QString RedisClient::scriptflush() 865 | { 866 | QString cmd("SCRIPT FLUSH"); 867 | 868 | auto reply = command(cmd); 869 | return reply.value.toString(); 870 | } 871 | 872 | QString RedisClient::scriptkill() 873 | { 874 | QString cmd("SCRIPT KILL"); 875 | 876 | auto reply = command(cmd); 877 | return reply.value.toString(); 878 | } 879 | 880 | QString RedisClient::scriptload(const QString & script) 881 | { 882 | QString cmd("SCRIPT LOAD "); 883 | cmd.append(script); 884 | 885 | auto reply = command(cmd); 886 | return reply.value.toString(); 887 | } 888 | 889 | QStringList RedisClient::sdiff(const QString & keys) 890 | { 891 | QString cmd("SDIFF "); 892 | cmd.append(keys); 893 | 894 | auto reply = command(cmd); 895 | return reply.value.toStringList(); 896 | } 897 | 898 | int RedisClient::sdiffstore(const QString & destination, const QString & keys) 899 | { 900 | QString cmd("SDIFFSTORE "); 901 | cmd.append(destination); 902 | cmd.append(" "); 903 | cmd.append(keys); 904 | 905 | auto reply = command(cmd); 906 | return reply.value.toInt(); 907 | } 908 | 909 | QStringList RedisClient::sinter(const QString & keys) 910 | { 911 | QString cmd("SINTER "); 912 | cmd.append(keys); 913 | 914 | auto reply = command(cmd); 915 | return reply.value.toStringList(); 916 | } 917 | 918 | int RedisClient::sinterstore(const QString & destination, const QString & keys) 919 | { 920 | QString cmd("SINTERSTORE "); 921 | cmd.append(destination); 922 | cmd.append(" "); 923 | cmd.append(keys); 924 | 925 | auto reply = command(cmd); 926 | return reply.value.toInt(); 927 | } 928 | 929 | bool RedisClient::sismember(const QString & key, const QString & member) 930 | { 931 | QString cmd("SISMEMBER "); 932 | cmd.append(key); 933 | cmd.append(" "); 934 | cmd.append(member); 935 | 936 | auto reply = command(cmd); 937 | return reply.value.toBool(); 938 | } 939 | 940 | QStringList RedisClient::smembers(const QString & key) 941 | { 942 | QString cmd("SMEMBERS "); 943 | cmd.append(key); 944 | 945 | auto reply = command(cmd); 946 | return reply.value.toStringList(); 947 | } 948 | 949 | bool RedisClient::smove(const QString & source, const QString & destination, const QString & member) 950 | { 951 | QString cmd("SMOVE "); 952 | cmd.append(source); 953 | cmd.append(" "); 954 | cmd.append(destination); 955 | cmd.append(" "); 956 | cmd.append(member); 957 | 958 | auto reply = command(cmd); 959 | return reply.value.toBool(); 960 | } 961 | 962 | QString RedisClient::spop(const QString & key) 963 | { 964 | QString cmd("SPOP "); 965 | cmd.append(key); 966 | 967 | auto reply = command(cmd); 968 | return reply.value.toString(); 969 | } 970 | 971 | QStringList RedisClient::srandmember(const QString & key, int count) 972 | { 973 | QString cmd("SRANDMEMBER "); 974 | cmd.append(key); 975 | cmd.append(" "); 976 | cmd.append(QString::number(count)); 977 | 978 | auto reply = command(cmd); 979 | return reply.value.toStringList(); 980 | } 981 | 982 | int RedisClient::srem(const QString & key, const QString & member) 983 | { 984 | QString cmd("SREM "); 985 | cmd.append(key); 986 | cmd.append(" "); 987 | cmd.append(member); 988 | 989 | auto reply = command(cmd); 990 | return reply.value.toInt(); 991 | } 992 | 993 | QStringList RedisClient::sunion(const QString & keys) 994 | { 995 | QString cmd("SUNION "); 996 | cmd.append(keys); 997 | 998 | auto reply = command(cmd); 999 | return reply.value.toStringList(); 1000 | } 1001 | 1002 | int RedisClient::sunionstore(const QString & destination, const QString & keys) 1003 | { 1004 | QString cmd("SUNIONSTORE "); 1005 | cmd.append(destination); 1006 | cmd.append(" "); 1007 | cmd.append(keys); 1008 | 1009 | auto reply = command(cmd); 1010 | return reply.value.toInt(); 1011 | } 1012 | 1013 | bool RedisClient::set(const QString & key, const QString & value) 1014 | { 1015 | QString cmd("SET "); 1016 | cmd.append(key); 1017 | cmd.append(" "); 1018 | cmd.append(value); 1019 | 1020 | auto reply = command(cmd); 1021 | 1022 | if (reply.value.toString() == "OK") 1023 | return true; 1024 | return false; 1025 | } 1026 | 1027 | int RedisClient::setrange(const QString & key, int offset, const QString & value) 1028 | { 1029 | QString cmd("SETRANGE "); 1030 | cmd.append(key); 1031 | cmd.append(" "); 1032 | cmd.append(QString::number(offset)); 1033 | cmd.append(" "); 1034 | cmd.append(value); 1035 | 1036 | auto reply = command(cmd); 1037 | return reply.value.toInt(); 1038 | } 1039 | 1040 | QStringList RedisClient::sort(const QString & key, const QString & conditions) 1041 | { 1042 | QString cmd("SORT "); 1043 | cmd.append(key); 1044 | cmd.append(" "); 1045 | cmd.append(conditions); 1046 | 1047 | auto reply = command(cmd); 1048 | return reply.value.toStringList(); 1049 | } 1050 | 1051 | int RedisClient::ttl(const QString & key) 1052 | { 1053 | QString cmd("TTL "); 1054 | cmd.append(key); 1055 | 1056 | auto reply = command(cmd); 1057 | return reply.value.toInt(); 1058 | } 1059 | 1060 | QString RedisClient::type(const QString & key) 1061 | { 1062 | QString cmd("TYPE "); 1063 | cmd.append(key); 1064 | 1065 | auto reply = command(cmd); 1066 | return reply.value.toString(); 1067 | } 1068 | 1069 | void RedisClient::init() 1070 | { 1071 | _express = new RedisExpress(this); 1072 | connect(_express, &RedisExpress::sigReply, [this](const QStringList &res) 1073 | { 1074 | if (res[1] == "message") 1075 | { 1076 | _msg.type = res[0]; 1077 | _msg.message = res[1]; 1078 | _msg.channel = res[2]; 1079 | _msg.value = res[3]; 1080 | 1081 | emit sigMessage(_msg); 1082 | } 1083 | else if (res[1] == "pmessage") 1084 | { 1085 | _msg.type = res[0]; 1086 | _msg.message = res[1]; 1087 | _msg.pattern = res[2]; 1088 | _msg.channel = res[3]; 1089 | _msg.value = res[4]; 1090 | 1091 | emit sigPMessage(_msg); 1092 | } 1093 | else 1094 | { 1095 | if (res[0] == "integer") 1096 | { 1097 | _msg.type = res[0]; 1098 | _msg.value = res[1].toInt(); 1099 | } 1100 | else if (res[0] == "list") 1101 | { 1102 | _msg.type = res[0]; 1103 | 1104 | QStringList list; 1105 | for (int i = 1; i < res.length(); i++) 1106 | { 1107 | list << res[i]; 1108 | } 1109 | 1110 | _msg.value = list; 1111 | } 1112 | else 1113 | { 1114 | _msg.type = res[0]; 1115 | _msg.value = res[1]; 1116 | } 1117 | 1118 | emit sigReply(_msg); 1119 | } 1120 | }); 1121 | } 1122 | -------------------------------------------------------------------------------- /RedisClient/RedisClient.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "RedisMsg.h" 4 | 5 | class RedisExpress; 6 | class RedisClient : public QObject 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | RedisClient(const QString &hostAddress, int port, QObject *parent = NULL); 12 | RedisClient(QObject *parent = NULL); 13 | 14 | QString getHostAddress(); 15 | void setHostAddress(const QString &hostAddress); 16 | void setPort(int port); 17 | int getPort(); 18 | bool isOpen(); 19 | void open(); 20 | void open(const QString &hostAddress, int port); 21 | void close(); 22 | 23 | RedisMsg command(const QString &str); 24 | 25 | void publish(const QString &channel, const QString &message); 26 | void subscribe(const QString &channel); 27 | void unsubscribe(const QString &channel); 28 | void psubscribe(const QString &pattern); 29 | void punsubscribe(const QString &pattern); 30 | 31 | int append(const QString &key, const QString &value); 32 | bool auth(const QString &password); 33 | QStringList blpop(const QString &key, int timeout); 34 | QStringList brpop(const QString &key, int timeout); 35 | QStringList brpoplpush(const QString &source, const QString &destination, int timeout); 36 | int decr(const QString &key); 37 | int decrby(const QString &key, int interval); 38 | int del(const QString &key); 39 | QString dump(const QString &key); 40 | bool exists(const QString &key); 41 | bool expire(const QString &key, int seconds); 42 | bool expireat(const QString &key, int timestamp); 43 | QVariant eval(const QString &script, int numkeys, const QString &keys, const QString &arguments); 44 | QVariant evalsha(const QString &sha1, int numkeys, const QString &keys, const QString &arguments); 45 | QString get(const QString &key); 46 | QString getrange(const QString &key, int start, int stop); 47 | 48 | int hdel(const QString &key, const QString &field); 49 | bool hexists(const QString &key, const QString &field); 50 | QString hget(const QString &key, const QString &field); 51 | QMap hgetall(const QString &key); 52 | 53 | int hincrby(const QString &key, const QString &field, int increment); 54 | float hincrbyfloat(const QString &key, const QString &field, float increment); 55 | QStringList hkeys(const QString &key); 56 | int hlen(const QString &key); 57 | QStringList hmget(const QString &key, const QString &field); 58 | bool hmset(const QString &key, QMap map); 59 | bool hset(const QString &key, const QString &field, const QString &value); 60 | bool hsetnx(const QString &key, const QString &field, const QString &value); 61 | QStringList hvals(const QString &key); 62 | 63 | 64 | int incr(const QString &key); 65 | int incrby(const QString &key, int interval); 66 | QStringList keys(const QString & pattern); 67 | int lindex(const QString &key, int index); 68 | int linsert(const QString &key, const QString &position, const QString &pivot, const QString &value); 69 | int llen(const QString &key); 70 | QString lpop(const QString &key); 71 | int lpush(const QString &key, const QString &value); 72 | int lpushx(const QString &key, const QString &value); 73 | QStringList lrange(const QString &key, int start, int stop); 74 | int lrem(const QString &key, int count, const QString &value); 75 | int lset(const QString &key, int index, const QString &value); 76 | bool ltrim(const QString &key, int start, int stop); 77 | QStringList mget(const QString &key); 78 | bool migrate(const QString & host, int port, const QString &key, int database, int timeout); 79 | bool move(const QString &key, int database); 80 | bool mset(QMap map); 81 | QVariant object(const QString &subcommand, const QString &arguments); 82 | bool persist(const QString &key); 83 | bool pexpire(const QString &key, int mseconds); 84 | bool pexpireat(const QString &key, int mstimestamp); 85 | int pttl(const QString &key); 86 | bool rename(const QString &key, const QString &newkey); 87 | bool renamex(const QString &key, const QString &newkey); 88 | bool restore(const QString &key, int ttl, const QString &value); 89 | QString rpop(const QString &key); 90 | QString rpoplpush(const QString &source, const QString &destination); 91 | int rpush(const QString &key, const QString &value); 92 | int rpushx(const QString &key, const QString &value); 93 | bool sadd(const QString &key, const QString &member); 94 | int scard(const QString &key); 95 | QStringList scriptexists(const QString &script); 96 | QString scriptflush(); 97 | QString scriptkill(); 98 | QString scriptload(const QString &script); 99 | QStringList sdiff(const QString &keys); 100 | int sdiffstore(const QString &destination, const QString &keys); 101 | QStringList sinter(const QString &keys); 102 | int sinterstore(const QString &destination, const QString &keys); 103 | bool sismember(const QString &key, const QString &member); 104 | QStringList smembers(const QString &key); 105 | bool smove(const QString &source, const QString &destination, const QString &member); 106 | QString spop(const QString &key); 107 | QStringList srandmember(const QString &key, int count); 108 | int srem(const QString &key, const QString &member); 109 | QStringList sunion(const QString &keys); 110 | int sunionstore(const QString &destination, const QString &keys); 111 | bool set(const QString &key, const QString &value); 112 | int setrange(const QString &key, int offset, const QString &value); 113 | QStringList sort(const QString &key, const QString &conditions); 114 | int ttl(const QString &key); 115 | QString type(const QString &key); 116 | 117 | private: 118 | RedisExpress *_express = NULL; 119 | RedisMsg _msg; 120 | int _nMaxTimeOfCmd = 3000; // command最长等待时间ms 121 | 122 | private: 123 | void init(); 124 | 125 | signals: 126 | void sigMessage(const RedisMsg &msg); 127 | void sigPMessage(const RedisMsg &msg); 128 | void sigReply(const RedisMsg &msg); 129 | }; 130 | -------------------------------------------------------------------------------- /RedisClient/RedisClient.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {B12702AD-ABFB-343A-A199-8E24837244A3} 30 | Qt4VSv1.0 31 | 10.0.16299.0 32 | 33 | 34 | 35 | Application 36 | v141 37 | 38 | 39 | Application 40 | v141 41 | 42 | 43 | 44 | $(MSBuildProjectDirectory)\QtMsBuild 45 | 46 | 47 | $(SolutionDir)$(Platform)\$(Configuration)\ 48 | 49 | 50 | $(SolutionDir)$(Platform)\$(Configuration)\ 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | true 70 | UNICODE;_UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_NETWORK_LIB;%(PreprocessorDefinitions) 71 | Disabled 72 | ProgramDatabase 73 | MultiThreadedDebugDLL 74 | .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtNetwork;%(AdditionalIncludeDirectories) 75 | true 76 | 77 | 78 | Console 79 | $(OutDir)\$(ProjectName).exe 80 | $(QTDIR)\lib;%(AdditionalLibraryDirectories) 81 | true 82 | qtmaind.lib;Qt5Cored.lib;Qt5Networkd.lib;%(AdditionalDependencies) 83 | 84 | 85 | UNICODE;_UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_NETWORK_LIB 86 | .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName)\.;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtNetwork 87 | .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp 88 | Moc'ing %(Identity)... 89 | 90 | 91 | 92 | 93 | true 94 | UNICODE;_UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_NETWORK_LIB;%(PreprocessorDefinitions) 95 | 96 | MultiThreadedDLL 97 | .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtNetwork;%(AdditionalIncludeDirectories) 98 | true 99 | 100 | 101 | Console 102 | $(OutDir)\$(ProjectName).exe 103 | $(QTDIR)\lib;%(AdditionalLibraryDirectories) 104 | false 105 | qtmain.lib;Qt5Core.lib;Qt5Network.lib;%(AdditionalDependencies) 106 | 107 | 108 | UNICODE;_UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_NETWORK_LIB 109 | .;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName)\.;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtNetwork 110 | .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp 111 | Moc'ing %(Identity)... 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /RedisClient/RedisClient.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} 14 | qrc;* 15 | false 16 | 17 | 18 | {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} 19 | qrc;* 20 | false 21 | 22 | 23 | {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11} 24 | moc;h;cpp 25 | False 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | 43 | 44 | Header Files 45 | 46 | 47 | Header Files 48 | 49 | 50 | 51 | 52 | Header Files 53 | 54 | 55 | -------------------------------------------------------------------------------- /RedisClient/RedisExpress.cpp: -------------------------------------------------------------------------------- 1 | #include "RedisExpress.h" 2 | #include 3 | #include 4 | 5 | RedisExpress::RedisExpress(QObject *parent) 6 | : QObject(parent) 7 | { 8 | init(); 9 | } 10 | 11 | RedisExpress::RedisExpress(const QString &hostAddress, int port, QObject *parent) 12 | : QObject(parent) 13 | { 14 | setHostAddress(hostAddress); 15 | setPort(port); 16 | init(); 17 | } 18 | 19 | RedisExpress::~RedisExpress() 20 | { 21 | 22 | } 23 | 24 | void RedisExpress::write(const QByteArray &data) 25 | { 26 | write(QString(data)); 27 | } 28 | 29 | void RedisExpress::write(const QString &str) 30 | { 31 | if (!_socket->isValid()) 32 | return; 33 | 34 | // 从字符串中分析并提取 35 | QChar c, nextC; 36 | QStringList parts; 37 | QString buffer; 38 | bool bCheck = false; 39 | for (int k = 0; k < str.length(); k++) 40 | { 41 | c = str.at(k); 42 | if (bCheck) 43 | { 44 | nextC = k < str.length() - 1 ? str 45 | .at(k + 1) : ' '; 46 | 47 | if (c == '\\' && nextC == '"') // 略过转义\"中的'\' 48 | { 49 | k++; 50 | continue; 51 | } 52 | else if (c == '"') // 遇到了第二个", 53 | { 54 | bCheck = false; 55 | } 56 | 57 | buffer += c; 58 | } 59 | else 60 | { 61 | if (!c.isSpace()) 62 | { 63 | if (c == '\\' && nextC == '"') // 略过转义\"中的'\' 64 | { 65 | k++; 66 | continue; 67 | } 68 | else if (c == '"') // 遇到第一个" 69 | { 70 | bCheck = true; 71 | } 72 | 73 | buffer += c; 74 | } 75 | else if (!buffer.isEmpty()) 76 | { 77 | parts << buffer; // 追加一个单词 78 | buffer.clear(); 79 | } 80 | } 81 | } 82 | 83 | if (!buffer.isEmpty()) // 当最后一个字母不是' '也不是'"'时 84 | { 85 | parts << buffer; 86 | } 87 | 88 | // 准备符合redis服务器接收的格式的数据 89 | QString sendData; 90 | sendData.append(QString("*%1\r\n").arg(parts.length())); // 总长度 91 | for (int i = 0; i < parts.length(); i++) 92 | { 93 | sendData.append(QString("$%1\r\n").arg(parts.at(i).length())); // 单词长度 94 | sendData.append(QString("%1\r\n").arg(parts.at(i))); // 单词 95 | } 96 | 97 | // 发送 98 | QTextStream stream(_socket); 99 | stream << sendData; 100 | stream.flush(); 101 | } 102 | 103 | QStringList RedisExpress::parseLine(const QByteArray &data) 104 | { 105 | if (data.isEmpty()) 106 | { 107 | return QStringList(); 108 | } 109 | 110 | QChar first = data.at(0); 111 | QString value; 112 | QStringList result; 113 | 114 | if (first == '+') // 字符串 115 | { 116 | value = data.mid(1); 117 | value.chop(2); // 删除\r\n 118 | 119 | result << "string" << value; 120 | } 121 | else if (first == '-') // 错误 122 | { 123 | value = data.mid(1); 124 | value.chop(2); 125 | 126 | result << "error" << value; 127 | } 128 | else if (first == ':') // 整型 129 | { 130 | value = data.mid(1); 131 | value.chop(2); 132 | 133 | result << "integer" << value; 134 | 135 | } 136 | else if (first == '$') // 字符串 137 | { 138 | auto index = data.indexOf("\r\n"); 139 | auto len = data.mid(1, index - 1).toInt(); 140 | if (len == -1) 141 | value = "NULL"; 142 | else 143 | value = data.mid(index + 2, len); 144 | 145 | result << "bulk" << value; 146 | } 147 | else if (first == '*') // 列表 148 | { 149 | auto index = data.indexOf("\r\n"); 150 | auto count = data.mid(1, index - 1).toInt(); // 列表中元素个数 151 | 152 | int len = -1; 153 | auto pos = index + 2; // 第一个元素索引 154 | result << "list"; 155 | 156 | for (int i = 0; i < count; i++) 157 | { 158 | index = data.indexOf("\r\n", pos); 159 | len = data.mid(pos + 1, index - pos - 1).toInt(); 160 | if (len == -1) 161 | result << "NULL"; 162 | else 163 | result << data.mid(index + 2, len); // 提取并追加元素 164 | 165 | pos = index + 2 + len + 2; // 下一个元素索引 166 | } 167 | } 168 | 169 | return result; 170 | } 171 | 172 | void RedisExpress::bind(const QString &address, int port) 173 | { 174 | _socket->bind(QHostAddress(address), port); 175 | } 176 | 177 | bool RedisExpress::isOpen() 178 | { 179 | return _socket->isValid(); 180 | } 181 | 182 | void RedisExpress::setHostAddress(const QString &hostAddress) 183 | { 184 | _hostAddress.setAddress(hostAddress); 185 | if (_socket->isValid()) // 如果已连接,重连新的地址 186 | { 187 | open(_hostAddress, _nPort); 188 | } 189 | } 190 | 191 | void RedisExpress::setPort(int port) 192 | { 193 | _nPort = port; 194 | if (_socket->isValid()) 195 | { 196 | open(_hostAddress, _nPort); 197 | } 198 | } 199 | 200 | void RedisExpress::open() 201 | { 202 | open(_hostAddress, _nPort); 203 | } 204 | 205 | void RedisExpress::open(const QString &hostAddress, int port) 206 | { 207 | open(QHostAddress(hostAddress), port); 208 | } 209 | 210 | void RedisExpress::open(const QHostAddress & hostAddress, int port) 211 | { 212 | _hostAddress = hostAddress; 213 | _nPort = port; 214 | _socket->connectToHost(hostAddress, port); 215 | } 216 | 217 | void RedisExpress::close() 218 | { 219 | _socket->disconnectFromHost(); 220 | } 221 | 222 | void RedisExpress::init() 223 | { 224 | _socket = new QTcpSocket(this); 225 | connect(_socket, &QTcpSocket::connected, this, &RedisExpress::sigConnected); 226 | connect(_socket, &QTcpSocket::disconnected, this, &RedisExpress::sigDisconnected); 227 | connect(_socket, &QTcpSocket::readyRead, [this]() 228 | { 229 | auto sl = parseLine(_socket->readAll()); // 解析 230 | emit sigReply(sl); 231 | }); 232 | connect(_socket, static_cast(&QTcpSocket::error), 233 | [this](QAbstractSocket::SocketError socketError) 234 | { 235 | QString error(QMetaType::typeName(socketError)); 236 | qDebug() << error; // 错误 237 | emit sigError(error); 238 | }); 239 | 240 | //connect(_socket, &QTcpSocket::connected, []() 241 | //{ 242 | // qDebug() << "connected"; 243 | //}); 244 | 245 | //connect(_socket, &QTcpSocket::disconnected, []() 246 | //{ 247 | // qDebug() << "disconnected"; 248 | //}); 249 | } 250 | -------------------------------------------------------------------------------- /RedisClient/RedisExpress.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class RedisExpress : public QObject 8 | { 9 | Q_OBJECT 10 | 11 | public: 12 | RedisExpress(const QString &hostAddress, int port, QObject *parent = NULL); 13 | RedisExpress(QObject *parent = NULL); 14 | ~RedisExpress(); 15 | 16 | void write(const QByteArray &data); // 发送 17 | void write(const QString &str); 18 | void bind(const QString &address, int port); 19 | bool isOpen(); 20 | void open(); // 连接 21 | void open(const QString &hostAddress, int port); 22 | void open(const QHostAddress &hostAddress, int port); 23 | void close(); // 关闭 24 | 25 | QString getHostAddress() { return _hostAddress.toString(); } 26 | void setHostAddress(const QString &hostAddress); 27 | 28 | int getPort() { return _nPort; } 29 | void setPort(int port); 30 | 31 | private: 32 | QHostAddress _hostAddress; 33 | int _nPort = 0; 34 | QTcpSocket *_socket = NULL; 35 | 36 | private: 37 | QStringList parseLine(const QByteArray &data); // 解析 38 | void init(); 39 | 40 | signals: 41 | void sigConnected(); // 已连上 42 | void sigDisconnected(); // 已断开 43 | void sigError(const QString &sError); // 错误 44 | void sigReply(const QStringList &sl); // 回复 45 | }; -------------------------------------------------------------------------------- /RedisClient/RedisMsg.cpp: -------------------------------------------------------------------------------- 1 | #include "RedisMsg.h" -------------------------------------------------------------------------------- /RedisClient/RedisMsg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class RedisMsg 6 | { 7 | public: 8 | QString type; 9 | QString message; 10 | QString pattern; 11 | QString channel; 12 | QVariant value; 13 | }; 14 | 15 | Q_DECLARE_METATYPE(RedisMsg) 16 | -------------------------------------------------------------------------------- /RedisClient/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "RedisClient.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | QCoreApplication a(argc, argv); 14 | 15 | QTimer timer; 16 | timer.setInterval(1000); 17 | timer.setSingleShot(true); 18 | QObject::connect(&timer, &QTimer::timeout, []() 19 | { 20 | QEventLoop loop; 21 | QTimer t; 22 | t.setSingleShot(true); 23 | QObject::connect(&t, &QTimer::timeout, [&loop]() 24 | { 25 | QTextStream in(stdin, QIODevice::ReadOnly); 26 | QString str; 27 | RedisClient client; 28 | client.open(QHostAddress(QHostAddress::LocalHost).toString(), 6379); 29 | //qDebug() << client.get("name"); 30 | //qDebug() << client.keys("*"); 31 | QObject::connect(&client, &RedisClient::sigMessage, [](const RedisMsg &msg) 32 | { 33 | qDebug() << msg.value; 34 | }); 35 | QObject::connect(&client, &RedisClient::sigReply, [](const RedisMsg &msg) 36 | { 37 | qDebug() << msg.value; 38 | }); 39 | while (in.readLineInto(&str)) 40 | { 41 | client.command(str); 42 | loop.processEvents(); 43 | } 44 | client.close(); 45 | loop.quit(); 46 | }); 47 | t.start(); 48 | 49 | loop.exec(); 50 | }); 51 | timer.start(); 52 | 53 | //RedisClient client; 54 | //client.open(QHostAddress(QHostAddress::LocalHost).toString(), 6379); 55 | ////qDebug() << client.get("name"); 56 | //qDebug() << client.keys("*"); 57 | //QObject::connect(&client, &RedisClient::sigMessage, [](const RedisMsg &msg) 58 | //{ 59 | // qDebug() << msg.value; 60 | //}); 61 | 62 | //QTcpSocket client; 63 | ////client.bind(QHostAddress(QHostAddress::LocalHost), 63791); 64 | //client.connectToHost(QHostAddress(QHostAddress::LocalHost), 6379); 65 | //QObject::connect(&client, &QTcpSocket::connected, []() 66 | //{ 67 | // qDebug() << "connected"; 68 | //}); 69 | 70 | //QObject::connect(&client, &QTcpSocket::disconnected, []() 71 | //{ 72 | // qDebug() << "disconnected"; 73 | //}); 74 | 75 | //QObject::connect(&client, &QTcpSocket::readyRead, [&client]() 76 | //{ 77 | // qDebug() << "readyRead:"; 78 | // qDebug() << QString(client.readAll()); 79 | //}); 80 | 81 | //QObject::connect(&client, static_cast(&QTcpSocket::error), 82 | // [](QAbstractSocket::SocketError socketError) 83 | //{ 84 | // qDebug() << QMetaType::typeName(socketError); 85 | //}); 86 | 87 | //client.write("HGETALL user\r\n"); 88 | return a.exec(); 89 | } 90 | --------------------------------------------------------------------------------