Windows
Windows 编程

redis 长连短连区别

PHP_REDIS_API int
redis_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
{
    zval *object;
    char *host = NULL, *persistent_id = "";
    zend_long port = -1, retry_interval = 0;
    strlen_t host_len, persistent_id_len;
    double timeout = 0.0, read_timeout = 0.0;
    redis_object *redis;
#ifdef ZTS
    /* not sure how in threaded mode this works so disabled persistence at
     * first */
    persistent = 0;
#endif
    //获取传入参数
    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
                                     "Os|ldsld", &object, redis_ce, &host,
                                     &host_len, &port, &timeout, &persistent_id,
                                     &persistent_id_len, &retry_interval,
                                     &read_timeout) == FAILURE)
    {
        return FAILURE;
    } else if (!persistent) {
        persistent_id = NULL; //如果是0的话则代表短连接 则先置空 redis_sock_create里 会把它清掉 不然的话 会复用
    }
    //连接超时
    if (timeout < 0L || timeout > INT_MAX) {
        zend_throw_exception(redis_exception_ce,
            "Invalid connect timeout", 0 TSRMLS_CC);
        return FAILURE;
    }
    //读取超时
    if (read_timeout < 0L || read_timeout > INT_MAX) {
        zend_throw_exception(redis_exception_ce,
            "Invalid read timeout", 0 TSRMLS_CC);
        return FAILURE;
    }
    //重来超时
    if (retry_interval < 0L || retry_interval > INT_MAX) {
        zend_throw_exception(redis_exception_ce, "Invalid retry interval",
            0 TSRMLS_CC);
        return FAILURE;
    }
    //判断是否是UNIX套接字
    /* If it's not a unix socket, set to default */
    if(port == -1 && host_len && host[0] != '/') {
        port = 6379;
    }
    //获取redis对象
    redis = PHPREDIS_GET_OBJECT(redis_object, object);
    //如果已经有一个sock对象,则先关闭这个对象,并且清理掉对象内容
    //这里要注意,如果你是一个长连接 redis_sock_disconnect 是不会关掉的链接的
    //而redis_free_socket会释放掉sock属性
    //所以说如果你是长连接的话,你连接的实例是不会被关闭的,但是你的部分参数会被清掉。
    /* if there is a redis sock already we have to remove it */
    if (redis->sock) {
        redis_sock_disconnect(redis->sock, 0 TSRMLS_CC);
        redis_free_socket(redis->sock);
    }
    //创建一个sock对象 这里把sock覆盖掉,如果是长连接的话 redis这个实例是不会被覆盖掉的,这里的sock可以理解为是一个参数对象
    redis->sock = redis_sock_create(host, host_len, port, timeout, read_timeout, persistent,
        persistent_id, retry_interval);
    //连接sock 如果是长连接的话 会直接返回0  如果是短连接的话 才会再次去以新的数据链接
    if (redis_sock_server_open(redis->sock TSRMLS_CC) < 0) {
        if (redis->sock->err) {
            zend_throw_exception(redis_exception_ce, ZSTR_VAL(redis->sock->err), 0 TSRMLS_CC);
        }
        redis_free_socket(redis->sock);
        redis->sock = NULL;
        return FAILURE;
    }
    return SUCCESS;
}


函数层级判断

前段时间我为Penu https://www.iwonmo.com/archives/1444.html 增加了函数功能,现在我想完成套嵌的编写方法。于是需要知道函数的层级数,以便执行函数。


      // TODO: code your application's behavior here.
        CString strHello;
        strHello=("Var=_Var(1)&ArrFun=_ArrFun(_RandFun(_ArrFun(2,3),_ArrFun(2,3)),3)&RandFun=_RandFun(_ErJI(),10)");
        CStringArray d,x,z,n;
        CString str;
        bool t=false;
        for (int i=0;i<strHello.GetLength();i++) {
            CString f(strHello[i]);
            if(f=="_") {t=true;str="";}
            if(t==true ) str+=strHello[i];
            if(f=="(") {
                t=false;
                if(str!=""){
                    d.Add(str.Left(str.GetLength()-1));
                    d.Add("(");
                    str="";
                }
            }
            if( f==")") d.Add(f);

        }

        //  此时d 为最小token

        int k=0;
        for(i=0;i<d.GetSize();i++){
            if(d.GetAt(i)=="(") k++;
            else if(d.GetAt(i)==")") k--;
            else if(d.GetAt(i) !="(" && d.GetAt(i) !=")"){
                if(k>=0){
                    x.Add(d.GetAt(i));
                    CString p;
                    p.Format("%d",k);
                    n.Add(p);
                }else{
                    k=0;
                }   
            }
        }

        // 此时 x 为 函数 n为函数层级 层级越大 越先执行

        for(i=0;i<x.GetSize();i++)

            printf("函数: %s,层级: %s\r\n",x.GetAt(i),n.GetAt(i));  

        printf("---\r\n");

        //排序

        for( i = 0; i < n.GetSize(); i++)
        {
            for(int j = i+1; j < n.GetSize(); j++)
            {
                if(_ttoi(n.GetAt(i))<_ttoi(n.GetAt(j)))
                {
                    CString t=x.GetAt(i);
                    x.SetAt(i,x.GetAt(j));
                    x.SetAt(j,t); 
                    t=n.GetAt(i);
                    n.SetAt(i,n.GetAt(j));
                    n.SetAt(j,t); 
                }
            }
        }

        for(i=0;i<x.GetSize();i++)

            printf("函数: %s,层级: %s\r\n",x.GetAt(i),n.GetAt(i));


屏幕快照 2019-02-01 下午5.26.41.png

会测接口测试工具(H.Test)

    微信截图_20190221102029.png

帮助文档

视频说明  文档说明  运行库(2017)  文件安全  码云历史

如系统为精简版或无法运行提示Dll问题,可打开运行库,选择Visual Studio 2017安装。

    函数说明

    Base64函数:_G64(all) | _U64(all)

        参数:

            all:所有可输入字符

        注:_Gxx:GB2312编码、_Uxx:UTF-8编码

    递增函数:_Var(num)

        参数:

            num:初始值。会在此值的基础上累加

    数组函数:_ArrFun(star,end | num)

        参数:

            star:字典开始位置【1】

            end:字典结束位置

        参数:

            num:直接索引

        字典格式:

            1,2,3,4,5  [字典为根目录下的ArrFun.txt]

    随机函数:_RandFun(num,len)

        参数:

            num:1:数字  2:字母  3:数字+字母

            len:返回文本长度

    随机整数函数:_NumFun(star,end)

        参数:

            star:开始数

            end:结束数

    函数使用

    新建php代码:

    <?php
        $ret=' | _Var:'.$_POST['Var'].
        ' | _ArrFun:'.$_POST['ArrFun'].
        ' | _RandFun:'.$_POST['RandFun'];
        exit($ret);

    POST数据格式:

    Var=_Var(1)&ArrFun=_ArrFun(1,3)&RandFun=_RandFun(3,10)

    返回结果:

    22:00:47[277]    | _Var:17 | _ArrFun:广州 | _RandFun:0joaoO46L7

    22:00:47[277]    | _Var:21 | _ArrFun:深圳 | _RandFun:tQVv3B8p5s

    ...

    22:00:47[277]    | _Var:9 | _ArrFun:上海 | _RandFun:7aqX44Cco5

    22:00:47[277]    | _Var:23 | _ArrFun:上海 | _RandFun:9aEQArrFPc

    更新日志


    SplitField

    将建表语句复制到剪贴板,然后打开SplitField就可以显示所有的字段,然后选择性的勾选就好了。建表语句可以直接从Navicat查看与复制。主要用于联查或子查询等一些需要选择字段的情况


    技术栈:Jdk1.8+Gradle   支持:win+osx




    2019.1.1  SplitField.zip

    增加对enum类型的分析

    修复剪贴板为空自动退出问题



    兼容版本:SplitField.jar.zip

    Win右键版本:SplitField.zip


    编写语法分析器分析Mysql字段

    看了一段时间的开发语言类的书籍,写了个小的例子,它定义了Mysql创建语句的语法表达式,实现了一个最小的语法解析器。


    语法分析器原理图(个人理解):


    开始.png


    Mysql语句:

    CREATE TABLE `fa_category` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `pid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父ID',
      `type` varchar(30) NOT NULL DEFAULT '' COMMENT '栏目类型',
      `name` varchar(30) NOT NULL DEFAULT '',
      `nickname` varchar(50) NOT NULL DEFAULT '',
      `flag` set('hot','index','recommend') NOT NULL DEFAULT '',
      `image` varchar(100) NOT NULL DEFAULT '' COMMENT '图片',
      `keywords` varchar(255) NOT NULL DEFAULT '' COMMENT '关键字',
      `description` varchar(255) NOT NULL DEFAULT '' COMMENT '描述',
      `diyname` varchar(30) NOT NULL DEFAULT '' COMMENT '自定义名称',
      `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
      `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
      `weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重',
      `status` varchar(30) NOT NULL DEFAULT '' COMMENT '状态',
      PRIMARY KEY (`id`),
      KEY `weigh` (`weigh`,`id`),
      KEY `pid` (`pid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='分类表';


    词法分析:

    import java.io.UnsupportedEncodingException;
    import java.util.ArrayList;
    import java.util.List;
    /**
     * 词法分析器 注:会分析出非终结符
     */
    public class lexicalAnalysis {
        /**
         * 分析出终结符或者非终结符
         * @param codeStr
         * @return
         */
        public static List<String> lex(String codeStr){
            //词法Token
            List<String> lexToken=new ArrayList<String>();;
            if("".equals(codeStr)) return null;
            String orignal = null;
            try {
                String tmpToken="";
                //对中文进行处理
                orignal = new String(codeStr.getBytes(), "UTF-8");
                for (int i = 0; i < orignal.length(); i++) {
                    String ch =String.valueOf(orignal.charAt(i));
                    if(ch.equals(" ") || ch.equals("(") || ch.equals(")"))
                    {
                        if(!tmpToken.equals("")){
                            lexToken.add(tmpToken);
                            tmpToken="";
                        }
                    }
                    else
                    {
                        tmpToken=tmpToken+ch;
                    }
                }
                //追加上最后一个临时Token
                if(!tmpToken.equals("")) lexToken.add(tmpToken);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return null;
            }
            //返回词法Token
            return lexToken;
        }
    }


    效果:

    词法分析-示例.png


    语法解析:

    import java.util.List;
    /**
     * 解析指定表达式的语法分析器
     */
    public class syntaxParsing {
        /**
         * 分析字段的语法解析器
         *
         * @param curr 当前的字段
         * @param nex  下一个字段
         * @return 是否是产生式
         */
        public static boolean parsing(String curr, String nex) {
            /**
             *  ①明确匹配产生式
             *  ②这里简单的认为:字段定义:字段类型 即为字段定义的产生式
             *  ③字段定义展开的产生式:重音符:字段名:重音符
             *  ④字段类型展开的产生式:内部字段名:参数(可选)
             **/
            if (curr.length() > 3)
                if (curr.substring(0, 1).equals("`")  && curr.substring(curr.length() - 1, curr.length()).equals("`") && internalType(nex))
                    return true;
                else return false;
            else return false;
        }
        /**
         * 判断Token是否是内部定义的类型
         *
         * @param nex 需要判断的Token
         * @return
         */
        public static boolean internalType(String nex) {
            /**
             * 这里不再对类型定义做产生式,而是粗略的进行判断
             */
            //转换为小写
            String i_nex = nex.toLowerCase();
            //判断是否是内部定义类型 :类型定义提取自nacicat for mysql
            switch (i_nex) {
                case "tinyint":
                    return true;
                case "smallint":
                    return true;
                case "mediumint":
                    return true;
                case "int":
                    return true;
                case "integer":
                    return true;
                case "bigint":
                    return true;
                case "float":
                    return true;
                case "double":
                    return true;
                case "char":
                    return true;
                case "varchar":
                    return true;
                case "tinyblob":
                    return true;
                case "tinytext":
                    return true;
                case "blob":
                    return true;
                case "text":
                    return true;
                case "mediumblob":
                    return true;
                case "mediumtext":
                    return true;
                case "longblob":
                    return true;
                case "longtext":
                    return true;
                case "date":
                    return true;
                case "time":
                    return true;
                case "year":
                    return true;
                case "datetime":
                    return true;
                case "timestamp":
                    return true;
                case "set":
                    return true;
            }
            return false;
        }
    }


    效果:

    语法解析.png

    源代码:https://github.com/iwonmo/Mysql-field-parsing