redis客户端连接到服务器的步骤
和大多数客户端连接到服务器一样,redis-cli连接到服务器也主要分为两个阶段,请求连接阶段和数据传送阶段。具体来讲redis-cli做的事情有:
1、以socket方式建立连接;
2,选择相应的数据库;
3,对客户端发送的命令进行编码;
4,发送客户端编码的数据(write);
5,接收服务器回应的数据(read);
6,解析接收的数据。
以下根据源码对客户端所做的事情进行分析。
/* Start interactive mode when no command is provided */
if (argc == 0 && !config.eval) {
/* Ignore SIGPIPE in interactive mode to force a reconnect */
signal(SIGPIPE, SIG_IGN);
/* Note that in repl mode we don't abort on connection error.
* A new attempt will be performed for every command send. */
cliConnect(0);
repl();
}
以上代码为redis-cli主函数中关于交互模式的部分,主要由cliConnect和repl构成,其中前者负责连接服务器,后者负责进行数据传输。
建立连接
关于客户端与服务器建立连接,我们知道主要的步骤分为、
1,创建socket(有一套固定的模式);
2,根据设定的ip及端口号,与服务器进行connet;
好的,这本来就是传统的做法,咱们看看redis它怎么做了呢?
它首先出定义了一个redis上下文结构,包含一次请求及回应的数据信息以及状态信息如下:
typedef struct redisContext {
int err;
char errstr[128];
int fd;
int flags;
char *obuf;
redisReader *reader;
enum redisConnectionType connection_type;
struct timeval *timeout;
struct {
char *host;
char *source_addr;
int port;
} tcp;
struct {
char *path;
} unix_sock;
} redisContext;
err、errstr为接收数据不正常时定义的变量,fd为客户端创建的sockfd,obuf为客户端的编码命令,reader为服务器返回的数据。并且要通过cliConnect进行初始化,定义tcp,fd等信息。
先看看cliConnect的操作
* Connect to the server. It is possible to pass certain flags to the function:
* CC_FORCE: The connection is performed even if there is already
* a connected socket.
* CC_QUIET: Don't print errors if connection fails. */
static int cliConnect(int flags) {
if (context == NULL || flags & CC_FORCE) {
if (context != NULL) {
redisFree(context);
}
if (config.hostsocket == NULL) {
context = redisConnect(config.hostip,config.hostport);
} else {
context = redisConnectUnix(config.hostsocket);
}
...
anetKeepAlive(NULL, context->fd, REDIS_CLI_KEEPALIVE_INTERVAL);
/* Do AUTH and select the right DB. */
if (cliAuth() != REDIS_OK)
return REDIS_ERR;
if (cliSelect() != REDIS_OK)
return REDIS_ERR;
}
return REDIS_OK;
}
flags用于表示客户端在已经连接到了服务器的情况下,是否还能在连接,0表示不允许连接,1表示允许连接(在改变客户端登录的服务器时会用到)。
redisConnect定义了context的ip,port;调用redisContextInit初始化字符串,调用redisContextConnectTcp(c,ip,port,NULL)完成了socket连接。
由于已经连接完成,cliSelect调用命令
reply = redisCommand(context,"SELECT %d",config.dbnum);
选0号数据库(默认)。
数据传输
在repl()中,使用了linenoise工具处理输入的行,字符串分割部分采用了cliSplitArgs,参数处理部分采用issueCommandRepeat。它调用redisAppendCommandArgv将参数编码,传递给context的obu;调用cliReadReply负责解码客户端接收到的数据;调用redisGetReply(在cliReadReply中)负责底层I/O数据的传输。
int redisGetReply(redisContext *c, void **reply) {
int wdone = 0;
void *aux = NULL;
/* Try to read pending replies */
if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)
return REDIS_ERR;
/* For the blocking context, flush output buffer and read reply */
if (aux == NULL && c->flags & REDIS_BLOCK) {
/* Write until done */
do {
if (redisBufferWrite(c,&wdone) == REDIS_ERR)
return REDIS_ERR;
} while (!wdone);
/* Read until there is a reply */
do {
if (redisBufferRead(c) == REDIS_ERR)
return REDIS_ERR;
if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)
return REDIS_ERR;
} while (aux == NULL);
}
/* Set reply object */
if (reply != NULL) *reply = aux;
return REDIS_OK;
}
主要是redisBufferWrite和redisBufferRead,分别向I/Obuf中写入和读取数据。redisGetReplyFromReader负责解码接收数据。
总结:
1,redis-cli在基本的客户端编程的基础上,增加了Context定义,可以知道数据的类型,数据的好坏。
2,增加了编码解码功能,一般编码解码功能可以使数据更安全,不知是不是因为这样才进行编码解码。
3,具体的实现部分还是需要进一步学习。
---------------------
redis客户端连接到服务器的步骤的更多相关文章
- 使用redis客户端连接windows和linux下的redis并解决无法连接redis的问题
搭建环境:linux是centos7.4(请注意centos7以下版本的防火墙跟centos7以上的不同,使用redis客户端连接redis时会有区别,建议使用centos7以上版本) 一.下载red ...
- Redis客户端连接以及持久化数据(三)
0.Redis目录结构 1)Redis介绍及部署在CentOS7上(一) 2)Redis指令与数据结构(二) 3)Redis客户端连接以及持久化数据(三) 4)Redis高可用之主从复制实践(四) 5 ...
- C#两大知名Redis客户端连接哨兵集群的姿势
前言 前面利用<Docker-Compose搭建Redis高可用哨兵集群>, 我们的思路是将Redis.Sentinel.Redis Client App链接到同一个网桥网络,这个网桥内的 ...
- redis客户端连接异常
本文参考:http://mdba.cn/2015/04/02/redistwemproxy-%e5%ae%a2%e6%88%b7%e7%ab%af%e8%bf%9e%e6%8e%a5%e5%bc%82 ...
- Redis客户端连接
Redis接受上配置监听TCP端口和Unix套接字客户端的连接,如果启用.当一个新的客户端连接被接受,如有以下操作进行: 客户端套接字置于非阻塞状态,因为Redis的使用复用和非阻塞I/O操作. TC ...
- Redis客户端连接池
使用场景 对于一些大对象,或者初始化过程较长的可复用的对象,我们如果每次都new对象出来,那么意味着会耗费大量的时间. 我们可以将这些对象缓存起来,当接口调用完毕后,不是销毁对象,当下次使用的时候,直 ...
- Redis 客户端连接
Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来自客户端的连接,当一个连接建立后,Redis 内部会进行以下一些操作: 首先,客户端 socket 会被设置为非阻 ...
- 使用 WebSocket 客户端连接 MQTT 服务器
简介 近年来随着 Web 前端的快速发展,浏览器新特性层出不穷,越来越多的应用可以在浏览器端或通过浏览器渲染引擎实现,Web 应用的即时通信方式 WebSocket 得到了广泛的应用. WebSock ...
- ESA2GJK1DH1K升级篇: 远程升级准备工作: 使用TCP客户端连接Web服务器实现http下载数据
一,根目录建一个文件 二,使用浏览器访问 http://47.92.31.46:80/1.txt 或者 http://47.92.31.46/1.txt 三,使用TCP客户端访问文件内容 3 ...
随机推荐
- [poj1698]Alice's Chance[网络流]
[转]原文:http://blog.csdn.net/wangjian8006/article/details/7926040 题目大意:爱丽丝要拍电影,有n部电影,规定爱丽丝每部电影在每个礼拜只有固 ...
- 【ACM】hdu_1808_Halloween treats_201308132022
Halloween treats Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- ubuntu 14.04升级PHP5.5.9 到5.6
升级的步骤:参考https://www.digitalocean.com/community/questions/how-to-upgrade-from-php-v-5-5-9-to-v-5-6 su ...
- java 9 Spring Cloud @EnableEurekaServer javax.xml.bind.JAXBContext not present
java 9 Spring Cloud @EnableEurekaServer javax.xml.bind.JAXBContext not present jdk 8下面还可以正常启动,jdk9 ...
- Nginx配置httpsserver
配置HTTPS主机.必须在server配置块中打开SSL协议,还须要指定服务器端证书和密钥文件的位置: server { listen 443; #要加密的域名 server_name www.te ...
- iOS开发使用Unwind Segue进行返回
我们在之前的一篇博客中谈到怎样使用dismissViewControllerAnimation()的方法在iOS中返回,如今我们有一个更为方便的方法来实现界面跳转之后的返回操作.使用的是Unwind ...
- 设置用root用户telnet到linux系统
默认情况下,ROOT用户不能以telnet方式连接Linux操作系统,而且也是不安全的.但从技术上来讲,是可以实现的. #mv /etc/securetty /etc/securetty.bak 保存 ...
- C++中的inline的用法
C++中的inline的用法 参考:http://www.cnblogs.com/fnlingnzb-learner/p/6423917.html 1. 引入inline关键字的原因 在c/c++中 ...
- 倒排索引PForDelta压缩算法——基本假设和霍夫曼压缩同
PForDelta算法 PForDelta算法最早由Heman在2005年提出,它允许同时对整个chunk数据(例128个数)进行压缩处理.基础思想是对于一个chunk的数列(例128个),认为其中占 ...
- Colored Sticks(trie)
http://poj.org/problem?id=2513 题意:给一些木棒,木棒两端图上颜色,将端点颜色相同的木棒连在一起,问是否能连成一条直线. 思路:将两端的颜色看成点,将木棒看成边,判断是否 ...