const priceNum = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']; function getPriceStr(price) { const priceMinType = ['', '拾', '佰', '仟']; const temFirstStrArr = price.split(''); temFirstStrArr.reverse(); const temStrArr = temFirstStrArr.map((item, index) => { if (+item) { return priceNum[+item] + priceMinType[index]; } return priceNum[+item]; }); temStrArr.reverse(); return temStrArr.join('').replace(/零+/g, '零').replace(/零$/, ''); } function priceTransform(price) { // '':为了能够识别1000亿 const priceBigType = ['元', '万', '亿', '']; const priceInt = parseInt(price); const typeCount = parseInt(String(priceInt).
Base64是最常见的用于传输8Bit字节码的编码方式之一,它是一种基于64个可打印字符来表示二进制数据的方法。
Base64是什么 Base64编码,是由64个字符组成编码集:26个大写字母AZ,26个小写字母az,10个数字0~9,符号“+”与符号“/”。Base64编码的基本思路是将原始数据的三个字节拆分转化为四个字节,然后根据Base64的对应表,得到对应的编码数据。
当原始数据凑不够三个字节时,编码结果中会使用额外的**符号“=”**来表示这种情况。
Base64编码表 码值字符码值字符码值字符码值字符0A16Q32g48w1B17R33h49x2C18S34i50y3D19T35j51z4E20U36k5205F21V37l5316G22W38m5427H23X39n5538I24Y40o5649J25Z41p57510K26a42q58611L27b43r59712M28c44s60813N29d45t61914O30e46u62+15P31f47v63/ Base64编码步骤 将原始数据按照每三个字节作为一组进行划分,每组一共是24个二进制位。再将这24个二进制位,每6个一划分,分为四组(6×4=24个二进制位)。然后在每组前面补上00,扩展成8×4=32个二进制位,即四个字节(因为每个字节前面有2个0,所以每个字节的最大值是63)。最后根据Base64编码表,将这四个字节的码值,转换为对应的Base64的字符即可。 Base64编码过程举例 情况1:正常的3个字节编码 将单词“PCB”转换为Base64编码:
“P”、“C”、"B"的ASCII值分别是80、67、66,对应的二进制值是0101 0000、0100 0011、0100 0010,将它们连成一个24位的二进制字符串010100000100001101000010。
将这个24位的二进制字符串,每6个一组分成4组:010100、000100、001101、000010。
在每组前面加两个00,扩展成32个二进制位,即四个字节:00010100、00000100、00001101、00000010。它们的十进制值分别是19、22、5、46。(最前面加上两个0只是为了凑成一个字节,实际上其本身的数值是没有变化的)
根据上表,得到每个值对应Base64编码,即U、E、N、C。
情况2:剩余2个字节编码 对于2个字节(16个二进制数)的情况,比如将“PC”转换为Base64编码:
转换方法同上,区别在于:
16个二进制数,每6个一组分割,最后剩余4个,这时再在后面补两个0凑成6个。然后还按照基础的方法转换,最后补一个“=”即可 转换过程如下表,最终将“PC”转换为了“UEM=”
情况3:剩余1个字节编码 对于12个字节(8个二进制数)的情况,比如将“P”转换为Base64编码:
转换方法同上,区别在于:
16个二进制数,每6个一组分割,最后剩余2个,后面要再补4个0然后还按照基础的方法转换,最后补两个“=”即可 转换过程如下表,最终将“P”转换为了“UA==”
Base64编解码C程序 编码程序 编码的程序设计思路,就是按照上面讲解的编码过程,每3个原始字符为一组,进行编码,得到4个base64的字符。对于不够3个字符的情况,编码的base64的字符后面补上一到两个=号。
#include <stdio.h> #include <string.h> /*base64符号表*/ const char *base64Arr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /*base64增补符号*/ const char paddingChar = '='; /** @func: base64_encode * @brief: base64编码 * @para: [srcData]:要进行编码的原始数据 * [resBase64]:base64编码结果 * @return:none */ void base64_encode(const unsigned char * srcData, char * resBase64) { int i=0; /*原始数据索引*/ int j=0; /*base64结果索引*/ unsigned char transIdx=0; // 索引是8位,但是高两位都为0 const int srcLen = strlen((const char*)srcData); /*每3个一组,进行编码*/ for(i=0; i < srcLen; i+=3) { /*取出第1个字符的高6位*/ transIdx = ((srcData[i] >> 2) & 0x3f); /*0011 1111*/ /*查表*/ resBase64[j++] = base64Arr[(int)transIdx]; /*取出第1个字符的低2位*/ transIdx = ((srcData[i] << 4) & 0x30); /*0011 0000*/ /*第1个字符后面还有字符*/ if (i + 1 < srcLen) { /*取出第2个字符的高4位,并与第1个字符的低2位进行组合*/ transIdx |= ((srcData[i + 1] >> 4) & 0x0f); /*0000 1111*/ /*查表*/ resBase64[j++] = base64Arr[(int)transIdx]; } else /*第1个字符后面没有字符了*/ { /*直接使用第1个字符的低2位查表*/ resBase64[j++] = base64Arr[(int)transIdx]; /*然后补上两个=号*/ resBase64[j++] = paddingChar; resBase64[j++] = paddingChar; break; /*没有数据了,break结束*/ } /*取出第2个字符的低4位*/ transIdx = ((srcData[i + 1] << 2) & 0x3c); /*0011 1100*/ /*第2个字符后面还有字符*/ if (i + 2 < srcLen) { /*取出第3个字符的高2位,并与第2个字符的低4位进行组合*/ transIdx |= ((srcData[i + 2] >> 6) & 0x03); /*0000 0011*/ /*查表*/ resBase64[j++] = base64Arr[(int)transIdx]; /*取出第3个字符的低6位*/ transIdx = srcData[i + 2] & 0x3f; /*0011 1111*/ /*查表*/ resBase64[j++] = base64Arr[(int)transIdx]; } else /*第2个字符后面没有字符了*/ { /*直接使用第2个字符的低4位查表*/ resBase64[j++] = base64Arr[(int)transIdx]; /*然后补上一个=号*/ resBase64[j++] = paddingChar; break; /*没有数据了,break结束*/ } } /*结束符*/ resBase64[j] = '\0'; } 解码程序 解码的程序设计思路,其实就是编码的反过程,把要解码的base64符号,每4个为一组,译码成3个字符。对于最后出现的=的情况,就说明是要结束了,直接使用剩余的base64符号进行译码,然后就结束了。
B+树 B+树是B树的一种变体,也属于平衡多路查找树,大体结构与B树相同,包含根节点、内部节点和叶子节点。多用于数据库和操作系统的文件系统中,由于B+树内部节点不保存数据,所以能在内存中存放更多索引,增加缓存命中率。另外因为叶子节点相连遍历操作很方便,而且数据也具有顺序性,便于区间查找。
B+树特点 B+树可以定义一个m值作为预定范围,即m路(阶)B+树。根节点可能是叶子节点,也可能是包含两个或两个以上子节点的节点。内部节点如果拥有k个关键字则有k+1个子节点。非叶子节点不保存数据,只保存关键字用作索引,所有数据都保存在叶子节点中。非叶子节点有若干子树指针,如果非叶子节点关键字为k1,k2,…kn,其中n=m-1,那么第一个子树关键字判断条件为小于k1,第二个为大于等于k1而小于k2,以此类推,最后一个为大于等于kn,总共可以划分出m个区间,即可以有m个分支。(判断条件其实没有严格的要求,只要能实现对B+树的数据进行定位划分即可,有些实现使用了m个关键字来划分区间,也是可以的)所有叶子节点通过指针链相连,且叶子节点本身按关键字的大小从小到大顺序排列。自然插入而不进行删除操作时,叶子节点项的个数范围为[floor(m/2),m-1],内部节点项的个数范围为[ceil(m/2)-1,m-1]。另外通常B+树有两个头指针,一个指向根节点一个指向关键字最小的叶子节点。在进行删除操作时,涉及到索引节点填充因子和叶子节点填充因子,一般可设叶子节点和索引节点的填充因子都不少于50%。 以下是一棵4阶B+树,
插入操作 假设现在构建一棵四阶B+树,开始插入“A”,直接作为根节点,
插入“B”,大于“A”,放右边,
插入“C”,按顺序排到最后,
继续插入“D”,直接添加的结果如下图,此时超过了节点可以存放容量,对于四阶B+树每个节点最多存放3个项,此时需要执行分裂操作,
分裂操作为,先选取待分裂节点中间位置的项,这里选“C”,然后将“C”项放到父节点中,因为这里还没有父节点,那么直接创建一个新的父节点存放“C”,而原来小于“C”的那些项作为左子树,原来大于等于“C”的那些项作为右子树。这里注意下非叶子节点存放的都是关键字,用作索引的,所以父节点存放的“C”项不包括数据,数据仍然存放在右子树。此外,还需要添加一个指针,由左子树指向右子树。
继续插入“M”,“M”大于“C”,往右子节点,
分别与“C”“D”比较,大于它们,放到最右边,
插入“L”,“L”大于“B”,往右子树,
“L”逐一与节点内项的值比较,根据大小放到指定位置,此时触发分裂操作,
选取待分裂节点中间位置的项“L”,然后将“L”项放到父节点中,按大小顺序将“L”放到指定位置,而原来小于“L”的那些项作为左子树,原来大于等于“L”的那些项作为右子树。父节点存放的“L”项不包括数据,数据仍然存放在右子树。此外,还需要在左子树中添加一个指向右子树的指针。
继续插入“K”,从根节点开始查找,逐一比较关键字,“K”大于“C”而小于“L”,往第二个分支,
在子节点中逐一比较,“K”最终落在最右边,
继续插入“J”,从根节点开始查找,逐一比较关键字,“J”大于“C”而小于“L”,往第二个分支,
在子节点中找到“J”的相应位置,此时超过了节点的容量,需要进行分裂操作,
选取待分裂节点中间位置的项“J”,然后将“J”项放到父节点中,按大小顺序将“J”放到指定位置,而原来小于“J”的那些项作为左子树,原来大于等于“J”的那些项作为右子树。父节点存放的“J”项不包括数据,数据仍然存放在右子树。此外,还需要在左子树中添加一个指向右子树的指针。
继续插入“I”,从根节点开始查找,逐一比较关键字,“I”大于“C”而小于“J”“L”,往第二个分支,
逐一比较找到“I”的插入位置,
继续插入“H”,从根节点开始查找,逐一比较关键字,“H”大于“C”而小于“J”“L”,往第二个分支,
“H”逐一与节点内的值比较,根据大小放到指定位置,此时触发分裂操作,
选取待分裂节点中间位置的项“H”,然后将“H”项放到父节点中,按大小顺序将“H”放到指定位置,而原来小于“H”的那些项作为左子树,原来大于等于“H”的那些项作为右子树。父节点存放的“H”项不包括数据,数据仍然存放在右子树。此外,还需要在左子树中添加一个指向右子树的指针。
但此时父节点超出了容量,父节点需要继续分裂操作,
选取待分裂节点中间位置的项“J”,然后将“J”项放到父节点中,但还不存在父节点,需要创建一个作为父节点。原来小于“J”的那些项作为左子树,原来大于“J”的那些项作为右子树。这是非叶子节点的分裂,操作对象都是用作索引的关键字,不必考虑数据存放问题。
插入“G”,从根节点开始查找,“G”小于“J”,往第一个分支,
逐一比较节点内项的值,“G”大于“C”小于“H”,往第二个分支,
逐一比较节点内项的值,找到“G”的位置并插入,
插入“F”,从根节点开始查找,“F”小于“J”,往第一个分支,
逐一比较节点内项的值,“F”大于“C”小于“H”,往第二个分支,
逐一比较节点内项的值,找到“F”的位置并插入,此时触发分裂操作,
选取待分裂节点中间位置的项“F”,然后将“F”项放到父节点中,按大小顺序将“F”放到指定位置,而原来小于“F”的那些项作为左子树,原来大于等于“F”的那些项作为右子树。父节点存放的“F”项不包括数据,数据仍然存放在右子树。此外,还需要在左子树中添加一个指向右子树的指针。
最后插入“E”,从根节点开始查找,“E”小于“J”,往第一个分支,
逐一比较节点内项的值,“E”大于“C”小于“F”,往第二个分支,
逐一比较节点内项的值,找打“E”适当的位置并插入。
从上面插入操作可以总结,插入主要就是涉及到分裂操作,而且要注意到非节点只保存了关键字作为索引,而数据都保存在叶子节点上,此外还需要使用指针将叶子节点连接起来。最终我们可以看到叶子节点的项按从小到大排列,因为有了指针使得可以很方便遍历数据。
查找操作 对B+树的查找与B树的查找差不多,从根节点开始查找,通过比较项的值找到对应的分支,然后继续往子树上查找。
比如查找“H”,“H”小于“J”,往第一个分支,
逐一比较节点中的项,发现应该往第四个分支,
逐一比较,找到“H”。
遍历操作 遍历操作首先是要先找到树最左边的叶子节点,然后就可以通过指针完成整棵树的遍历了。
从根节点开始,一直往第一个分支走,
继续往第一个分支走,
第一个叶子节点有两个项,接着根据指针跳到第二个叶子节点,
第二个节点有三个项,根据指针继续往下一个节点,
该节点有两个项,根据指针继续往下一个节点,
不断根据指针往下,
往下,
完成整棵树的遍历。
作者:超人汪小建
链接:https://juejin.im/post/5b9073f9f265da0acd209624
1.下载Git
2.在IEDEA中配置Git位置
3.左下角点击Git展开,右键选择自己所需要的分支,点击Chekout。切换成功。
4.右上角依次点击三个按钮。①先拉下来原项目,因为之前可能有人先提交了,所以要先更新再提交上传②commit √ ③上传
原文:https://zhuanlan.zhihu.com/p/63179839 一、从网卡接收数据说起 下图是一个典型的计算机结构图,计算机由CPU、存储器(内存)、网络接口等部件组成。了解epoll本质的第一步,要从硬件的角度看计算机怎样接收网络数据。
计算机结构图(图片来源:linux内核完全注释之微型计算机组成结构)
下图展示了网卡接收数据的过程。在①阶段,网卡收到网线传来的数据;经过②阶段的硬件电路的传输;最终将数据写入到内存中的某个地址上(③阶段)。这个过程涉及到DMA传输、IO通路选择等硬件有关的知识,但我们只需知道:网卡会把接收到的数据写入内存。
网卡接收数据的过程
通过硬件传输,网卡接收的数据存放到内存中。操作系统就可以去读取它们。
二、如何知道接收了数据? 了解epoll本质的第二步,要从CPU的角度来看数据接收。要理解这个问题,要先了解一个概念——中断。
计算机执行程序时,会有优先级的需求。比如,当计算机收到断电信号时(电容可以保存少许电量,供CPU运行很短的一小段时间),它应立即去保存数据,保存数据的程序具有较高的优先级。
一般而言,由硬件产生的信号需要cpu立马做出回应(不然数据可能就丢失),所以它的优先级很高。cpu理应中断掉正在执行的程序,去做出响应;当cpu完成对硬件的响应后,再重新执行用户程序。中断的过程如下图,和函数调用差不多。只不过函数调用是事先定好位置,而中断的位置由“信号”决定。
中断程序调用
以键盘为例,当用户按下键盘某个按键时,键盘会给cpu的中断引脚发出一个高电平。cpu能够捕获这个信号,然后执行键盘中断程序。下图展示了各种硬件通过中断与cpu交互。
cpu中断(图片来源:net.pku.edu.cn)
现在可以回答本节提出的问题了:当网卡把数据写入到内存后,网卡向cpu发出一个中断信号,操作系统便能得知有新数据到来,再通过网卡中断程序去处理数据。
三、进程阻塞为什么不占用cpu资源? 了解epoll本质的第三步,要从操作系统进程调度的角度来看数据接收。阻塞是进程调度的关键一环,指的是进程在等待某事件(如接收到网络数据)发生之前的等待状态,recv、select和epoll都是阻塞方法。了解“进程阻塞为什么不占用cpu资源?”,也就能够了解这一步。
为简单起见,我们从普通的recv接收开始分析,先看看下面代码:
//创建socket int s = socket(AF_INET, SOCK_STREAM, 0); //绑定 bind(s, ...) //监听 listen(s, ...) //接受客户端连接 int c = accept(s, ...) //接收客户端数据 recv(c, ...); //将数据打印出来 printf(...) 这是一段最基础的网络编程代码,先新建socket对象,依次调用bind、listen、accept,最后调用recv接收数据。recv是个阻塞方法,当程序运行到recv时,它会一直等待,直到接收到数据才往下执行。
插入:如果您还不太熟悉网络编程,欢迎阅读我编写的《Unity3D网络游戏实战(第2版)》,会有详细的介绍。 那么阻塞的原理是什么?
工作队列
操作系统为了支持多任务,实现了进程调度的功能,会把进程分为“运行”和“等待”等几种状态。运行状态是进程获得cpu使用权,正在执行代码的状态;等待状态是阻塞状态,比如上述程序运行到recv时,程序会从运行状态变为等待状态,接收到数据后又变回运行状态。操作系统会分时执行各个运行状态的进程,由于速度很快,看上去就像是同时执行多个任务。
下图中的计算机中运行着A、B、C三个进程,其中进程A执行着上述基础网络程序,一开始,这3个进程都被操作系统的工作队列所引用,处于运行状态,会分时执行。
工作队列中有A、B和C三个进程
等待队列
当进程A执行到创建socket的语句时,操作系统会创建一个由文件系统管理的socket对象(如下图)。这个socket对象包含了发送缓冲区、接收缓冲区、等待队列等成员。等待队列是个非常重要的结构,它指向所有需要等待该socket事件的进程。
创建socket
当程序执行到recv时,操作系统会将进程A从工作队列移动到该socket的等待队列中(如下图)。由于工作队列只剩下了进程B和C,依据进程调度,cpu会轮流执行这两个进程的程序,不会执行进程A的程序。所以进程A被阻塞,不会往下执行代码,也不会占用cpu资源。
socket的等待队列
ps:操作系统添加等待队列只是添加了对这个“等待中”进程的引用,以便在接收到数据时获取进程对象、将其唤醒,而非直接将进程管理纳入自己之下。上图为了方便说明,直接将进程挂到等待队列之下。
唤醒进程
当socket接收到数据后,操作系统将该socket等待队列上的进程重新放回到工作队列,该进程变成运行状态,继续执行代码。也由于socket的接收缓冲区已经有了数据,recv可以返回接收到的数据。
四、内核接收网络数据全过程 这一步,贯穿网卡、中断、进程调度的知识,叙述阻塞recv下,内核接收数据全过程。
如下图所示,进程在recv阻塞期间,计算机收到了对端传送的数据(步骤①)。数据经由网卡传送到内存(步骤②),然后网卡通过中断信号通知cpu有数据到达,cpu执行中断程序(步骤③)。此处的中断程序主要有两项功能,先将网络数据写入到对应socket的接收缓冲区里面(步骤④),再唤醒进程A(步骤⑤),重新将进程A放入工作队列中。
内核接收数据全过程
唤醒进程的过程如下图所示。
唤醒进程
以上是内核接收数据全过程
这里留有两个思考题,大家先想一想。
其一,操作系统如何知道网络数据对应于哪个socket?
其二,如何同时监视多个socket的数据?
第一个问题:因为一个socket对应着一个端口号,而网络数据包中包含了ip和端口的信息,内核可以通过端口号找到对应的socket。当然,为了提高处理速度,操作系统会维护端口号到socket的索引结构,以快速读取。
第二个问题是多路复用的重中之重,是本文后半部分的重点!
项目Github地址: https://github.com/baiye21/ShiroDemo SpringBoot 基于Shiro + Jwt + Redis的用户权限管理 (一) 简介与配置 SpringBoot 基于Shiro + Jwt + Redis的用户权限管理 (二) 认证 SpringBoot 基于Shiro + Jwt + Redis的用户权限管理 (三) 鉴权 一,ShiroFilterFactoryBean配置 FilterChainDefinitionMap排除需要权限才能访问的URL,这样才能进入自定义过滤器JwtFilter中进行后续验证。
比如,测试权限的URl为/role/OneRole.do,它不需要写入FilterChainDefinitionMap中,如下图
二,自定义ShiroSessionManager 认证成功后,将shiro生成的sessionid保存到了access_token中,所以携带token访问时,需要从token将其取出。
com.demo.config.ShiroConfig中
/** * SecurityManager 是 Shiro 架构的核心,通过它来链接Realm和用户(文档中称之为Subject.) */ @Bean public SecurityManager securityManager( @Qualifier("passwordRealm") PasswordRealm passwordRealm, @Qualifier("jwtRealm") JwtRealm jwtRealm, @Qualifier("demoRealm") DemoRealm demoRealm, @Qualifier("userModularRealmAuthenticator") UserModularRealmAuthenticator userModularRealmAuthenticator) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 设置realm securityManager.setAuthenticator(userModularRealmAuthenticator); List<Realm> realms = new ArrayList<>(); // 添加多个realm realms.
方法一
nvidia-smi -l 1 nvidia-smi是显示一下
watch -n 1 -d nvidia-smi 每隔一秒刷新一次,时间参数可以更改
比如 watch -n 0.1 -d nvidia-smi 就是每个0.1秒刷新一次
方法二
import os import time while 1: os.system('nvidia-smi') time.sleep(1) # 1秒刷新一次 os.system('cls') # 这个是清屏操作
大学计算机基础 试题题库及答案
一、单选题练习 1.完整的计算机系统由( C )组成。A.运算器、控制器、存储器、输入设备和输出设备B.主机和外部设备C.硬件系统和软件系统D.主机箱、显示器、键盘、鼠标、打印机2.以下软件中,( D )不是操作系统软件。A.Windows xp???????? B.unix??????????C.linux???? D.microsoft office3.用一个字节最多能编出( D )不同的码。A. 8个???????????????? B. 16个?????????? C. 128个????????????D. 256个4.任何程序都必须加载到( C )中才能被CPU执行。????A. 磁盘?????????????? B. 硬盘????????????C. 内存????????????D. 外存5.下列设备中,属于输出设备的是( A )。A.显示器 ?????? B.键盘 ???? C.鼠标 ???? D.手字板6.计算机信息计量单位中的K代表( B )。????A. 102???????????????? B. 210??????????????C. 103??????????????D. 287.RAM代表的是( C )。????A. 只读存储器???????? B. 高速缓存器?????? C. 随机存储器?????? D. 软盘存储器8.组成计算机的CPU的两大部件是( A )。A.运算器和控制器????B. 控制器和寄存器?? C.运算器和内存????D. 控制器和内存9.在描述信息传输中bps表示的是( D )。 A.每秒传输的字节数?????????????????? B.每秒传输的指令数C.每秒传输的字数???????????????????? D.每秒传输的位数10.微型计算机的内存容量主要指( A )的容量。A. RAM??????????????B. ROM????????????C. CMOS?????????? D. Cache11.十进制数27对应的二进制数为( D )。A.1011?
光驱是电脑里读取光盘的一个配件。随着多媒体的应用越来越广泛,使得光驱在笔记本诸多配件中的已经成标准配置。最近有win7用户反映电脑光驱读不出光盘了,这有可能是因为dvd区域没有给定造成的,那么遇到电脑光驱读不出光盘怎么办呢?今天小编就为大家介绍win7系统光驱读不出光盘数据的解决方法。
方法一:
1、首先来到桌面,右键点击“计算机”打开菜单,然后选择“管理”;
2、进入“计算机管理”窗口后,点击“设备管理器”,如图所示;
3、然后在右侧窗口找到“DVD/CD-ROM驱动器”并展开,并右键点击其子项打开菜单,选择“属性”;
4、进入属性窗口后,切换到“DVD区域”选项卡,在地理区域窗口下拉滑块,选择区域为“中国”(有次数限制),再点击“确定”即可。
方法二:
1、,如果什么的方法没有解决问题,可以试试修改注册表,首先在桌面按下“Win + R”打开“运行”窗口,输入“regedit”并点击确定打开注册表;
2、进入“注册表编辑器”窗口后,依次展开“HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\CD Burning\AudioBurnhandlers\{cdc32574-7521-90c3-8d5605a34933}”。
3、然后右侧窗口的空白处,右键打开菜单,选择“新建--二进制值”;
4、然后将此项命名为“StagingPath”,如图所示;
5、然后双击打开刚刚新建的“StagingPath”二进制值,打开“编辑字符串”窗口后,将“数值数据”设置为“C:Users\gnong\AppData\Local\Microsoft\Windows\Burn\Burn”,然后点击确定即可。
关于win7系统光驱读不出光盘的解决方法小编就为大家介绍到这里了,遇到怕光驱读不出光盘数据的用户,不妨按照本篇教程介绍的方法来解决。
最近一直在优化行情推送系统,有不少优化心得跟大家分享下。性能方面提升最明显的是时延,在单节点8万客户端时,时延从1500ms优化到40ms,这里是内网mock客户端的得到的压测数据。
对于订阅客户端数没有太执着量级的测试,弱网络下单机8w客户端是没问题的。当前采用的是kubenetes部署方案,可灵活地扩展扩容。
架构图 push-gateway是推送的网关,有这么几个功能:第一点是为了做鉴权;第二点是为了做接入多协议,我们这里实现了websocket, grpc, grpc-web,sse的支持;第三点是为了实现策略调度及亲和绑定等。
push-server 是推送服务,这里维护了订阅关系及监听mq的新消息,继而推送到网关。
问题一:并发操作map带来的锁竞争及时延 推送的服务需要维护订阅关系,一般是用嵌套的map结构来表示,这样造成map并发竞争下带来的锁竞争和时延高的问题。
// xiaorui.cc {"topic1": {"uuid1": client1, "uuid2": client2}, "topic2": {"uuid3": client3, "uuid4": client4} ... } 已经根据业务拆分了4个map,但是该订阅关系是嵌套的,直接上锁会让其他协程都阻塞,阻塞就会造成时延高。
加锁操作map本应该很快,为什么会阻塞?上面我们有说过该map是用来存topic和客户端列表的订阅关系,当我进行推送时,必然是需要拿到该topic的所有客户端,然后进行一个个的send通知。(这里的send不是io.send,而是chan send,每个客户端都绑定了缓冲的chan)
解决方法:在每个业务里划分256个map和读写锁,这样锁的粒度降低到1/256。除了该方法,开始有尝试过把客户端列表放到一个新的slice里返回,但造成了 GC 的压力,经过测试不可取。
// xiaorui.cc sync.RWMutex map[string]map[string]client 改成这样 m *shardMap.shardMap 分段map的库已经推到github[1]了,有兴趣的可以看看。
问题二:串行消息通知改成并发模式 简单说,我们在推送服务维护了某个topic和1w个客户端chan的映射,当从mq收到该topic消息后,再通知给这1w个客户端chan。
客户端的chan本身是有大buffer,另外发送的函数也使用 select default 来避免阻塞。但事实上这样串行发送chan耗时不小。对于channel底层来说,需要goready等待channel的goroutine,推送到runq里。
下面是我写的benchmark[2],可以对比串行和并发的耗时对比。在mac下效果不是太明显,因为mac cpu频率较高,在服务器里效果明显。
串行通知,拿到所有客户端的chan,然后进行send发送。
for _, notifier := range notifiers { s.directSendMesg(notifier, mesg) } 并发send,这里使用协程池来规避morestack的消耗,另外使用sync.waitgroup里实现异步下的等待。
// xiaorui.cc notifiers := []*mapping.StreamNotifier{} // conv slice for _, notifier := range notifierMap { notifiers = append(notifiers, notifier) } // optimize: direct map struct taskChunks := b.
《计算机网络概述ppt课件.pptx》由会员分享,提供在线免费全文阅读可下载,此文档格式为pptx,更多相关《计算机网络概述ppt课件.pptx》文档请在天天文库搜索。
1、第3章 计算机网络基础知识内容计算机网络概述接入Internet获取网络信息网络信息交流【章节脉络】3.1 计算机网络概述1.计算机网络的概念定义计算机网络是指将地理位置不同且功能相对独立的多个计算机系统通过通信线路和设备相互连在一起、由专门的网络操作系统进行管理,以实现资源共享的系统。。2.计算机网络的分类常见的分类方法有以下几种:按通信介质分为:有线网络和无线网络。按使用网络的对象分为:公众网络和专用网络。按网络传输技术分为:广播式网络和点到点式网络。按地理覆盖范围分为:广域网(WAN)、城域网(MAN)和局域网(LAN)。3.计算机网络的主要功能4.计算机网络的组成(1)从逻辑组成上讲,计算机网络是由“通信子网”和“资源子网”两部分。(2)从物理组成上讲,计算机网络是由网络硬件和网络软件组成。计算机网络硬件:网络服务器、网络工作站、网络设备(集线器、交换机、路由器、调制解调器Mode。
2、m等)、传输介质(同轴电缆、双绞线、光纤等)。计算机网络软件:网络操作系统、网络协议软件、网络管理软件、网络通信软件、网络应用软件等。路由器同轴电缆光纤5.计算机网络协议计算机网络协议为计算机网络中进行数据交换而建立的规则、标准或约定的集合。网络协议是由三个要素组成:语法、语义、时序6.计算机网络拓扑结构在计算机网络中,我们把计算机、终端、通信处理机等设备抽象成点,把连接这些设备的通信线路抽象成线,并将由这些点和线所构成的拓扑称为网络拓扑结构。常见的网络拓扑结构有总线型、星型、环型、树型和网状型等。课堂练习单项选择题例1、计算机网络的主要功能或目标是( ) 。A.数据通信 B.电子邮件 C.资源共享 D.Internet答案:C例2、( )提供网络访问、网络资源共享和数据处理业务。A.通信子网 B.资源子网 C.数据子网 D.设备子网答案:B例3、以下哪个不是网络拓扑结构? ( ) 。A.总线型 B.星型 C.开放型 D.环型答案:C课堂练习判断题例1、双绞线不仅可以传输数字信号,也可以传输模拟信号。答案: √例2、网络操作系统目前主要有 UNIX 系统、Novell 网络操作系统、OS/2、Windows Server 2003 等。答案:×。
鼠标在使用过程中,总是会遇到形形色色的问题,比如有用户经常反映说鼠标插电脑上没反应,鼠标灯虽然亮了但是光标是无法移动的,碰上这样的问题是怎么会是回事呢,排除鼠标本身的问题,可能是系统原因,本文就给大家说说鼠标连接电脑没反应的解决步骤吧。
具体步骤如下:
如果电脑鼠标连接电脑没反应,无法使用的原因可能zhi就是鼠标损坏或者电脑设置有问题。以下为电脑设置问题的解决法子,如果依照方法设置无效,请考虑更换或者维修鼠标。
1.按下F5键刷新,再按下Windows徽标键+D键进入桌面,图为Windows徽标键。
2.用方向键选中“我的电脑”,按下菜单键(此键的作用与鼠标右键一致),图为Windows菜单键。
3.用方向键选中“管理”,并按Enter键。
4.用方向键选中“系统工具”,并按Tab键将高亮光标转移至右方的菜单,再用方向键选中“设备管理器”并按Enter键。
5.用方向键选中“鼠标和其他指针设备”,按右方向键展开并按Enter键。
6.用Tab键将光标移至“设备用法”上,用方向键选择“使用这个设备(启用)”,最后按Enter键,返回桌面并刷新即可。
关于鼠标连接电脑没反应的解决步骤就给大家介绍到这边了,有遇到一样情况的用户们可以参考上面的方法来进行解决吧。
我要分享到:
上大学选择专业是一件大事,决定你后期的职业规划以及发展。张雪峰老师曾经说过,考研不能绝对影响你的一生,但是会提高你的竞争力,但是如果选择这几个专业,考研也不能拯救。
1、心理类专业
心理专业有很多人愿意去学习,认为这个专业有很多奥妙之处,还可以帮助他人。但是目前不论在国内还是国外学习心理专业,以后只能去一些心理诊所或者工作室,所以心理专业的学生就业率都比较低。还有一方面原因是很多人不太注重心理方面的疾病,而且大多数人都不愿意承认自己有心理疾病。如果对这方面很感兴趣,建议可以在大学里选修这门专业,而不是专修这门专业,否则考研上名牌大学也很难拯救。
2、生物工程类专业
生物工程专业给人一种高大上的感觉,但其实这门专业就业率很低。因为生物科学专业的人从事科研方面的会多一点,但是直接去就业很难有对口的工作。除非有出国的打算,否则不管是本科还是研究生,都很难找到工作。
3、环境方面的专业
环境方面的专业包括环境工程、环境技术等专业,这些专业在社会上的需求比较小,就业情况不是很乐观。985/211大学毕业的学生都很难就业,普通本科学习这个专业,更是难上加难。虽然很多人主要的目的是本科、研究生学历,专业无所谓,但是大学四年、研究生三年总该学点对以后真正有用的东西,否则拿到学历也没有什么用处,只能转行。
4、高尔夫管理专业
这个专业可能有很多都没有听过,但确实是有这个专业。早在深圳大学就开设了这个专业,现在有很多大学比如北京林业大学、同济大学、广州大学等高校也相继开设了与高尔夫相关专业。不管在大城市还是小城市这个专业就业机会很少,就算是考上研究生,就业情况也不乐观。
有很多专业不一定是学历越高就越好,还是要具体问题具体分析。今天小编给大家介绍的这几个专业,在选择的时候一定要谨慎,不到万不得已不要报考。当然也可以在考研的时候换专业,这样就能实现高学历高就业了。
特别声明:以上文章内容仅代表作者本人观点,不代表新浪网观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与新浪网联系。
使用树莓派制作一个CODESYS的PLC控制器 树莓派上实现控制器1. 安装CodeSys编程环境1.1 下载CODESYS1.2 安装CODESYS开发环境1.3 运行CODESYS开发环境 2. 运行CODESYS开发环境2.1 创建项目2.2 编辑程序2.3 编译程序2.4 下载程序 3. 运行结果3.1 接口3.2 可视化3.3 支持的现场总线 4. 后续 树莓派上实现控制器 大家对树莓派都不陌生,可以作为一个微型计算机,使用SSH可以在计算机上编辑,如果有支持HDMI的显示器,有USB鼠标和键盘就可以像一个计算机一样使用。有LibreOffice做表格和文字处理等。一个树莓派的界面如下:
介绍树莓派的文章都很多了,在这里不做赘述了,主要介绍使用一个树莓派来作为一个PLC及采取的Codesys来编辑树莓派PLC。其实就是在树莓派上运行一个CodeSys的runtime。实现一个PLC可以完成的全部的功能。
1. 安装CodeSys编程环境 首先要在计算机上安装CodeSys的PLC编辑的软件。
1.1 下载CODESYS 软件的英文名称是CODESYS开发系统:
可以看到,开发系统有支持32位的,也有支持64位。我这里选择了64位的系统。下载需要有一个账户,这个软件是免费的。所以在英文网站上先注册账户,然后下载就可以了。
下载首先是下载一个程序,如图:
名称:CODESYS 64 3.5.17.0.exe
1.2 安装CODESYS开发环境 双击上面的CODESYS 64 3.5.17.0.exe开始安装,时间比较长。要有耐心,一定要关闭防病毒的软件,我装了360安全卫士,关闭。然后安装。不然在过程中总是问要不要允许安装。安装完成了就可以运行CODESYS 3.5 SP17,我计算机上的图标如下:
1.3 运行CODESYS开发环境 运行的界面如上。先不要着急建立系统,在工具栏目上选择包管理器,如图:
点击包管理器及选择安装,出现下面的画面,这是我已经下载的包。要安装的包有两个:
CODESYS Edge Gateway for Linux 4.1.0.0.packageCODESYS Control for Raspberry PI 4.1.0.0.package 在树莓派的包安装时需要这个Edge Gateway,我看早一个版本的还不需要这个Edge Gateway安装。
安装完成后就可以进行对树莓派进行编程了。
2. 运行CODESYS开发环境 2.1 创建项目 在CODESYS环境下选择新建一个树莓派的控制器的项目。
我们选择一个名称为RASP002的项目,采用标准项目的模板。然后确定。
在下面的画面中我们可以选择要建立的项目的硬件类型。
在这其中可以看到有许多种的硬件可以选择。最简单的是选择一个CODESYS Control Win V3 x64的项目。这个项目是在我们的电脑上创建一个软PLC。当然,如果没有许可证,这个PLC运行两个小时就会退出。我们现在有了CODESYS Control for Raspberry Pi, 在这里选择这个设备。选择了以后剩下的事情就可以让计算机来工作了,要有大约1分钟的时间,给我们创建了这个项目。如图:
一、AX,BX,CX,DX寄存器作用 寄存器AX、BX、CX、DX是8086CPU中的四个通用寄存器,主要用来存放一般性的数据。
二、AX,BX,CX,DX寄存器的结构 因为8086CPU寄存器是16位结构,所以一个寄存器可以存放两个字节,同时为了兼容性,这四个寄存器中每一个寄存器也可以单独分为两个独立的寄存器。即AX=AH(高八位)+AL(低八位),另外三个类似。
1. 前言 今天在做一个文件编辑器,然后发现读取txt文件的时候,中文的显示乱码,然后在网上查了一些方法,没用,自己摸索了一下,找出了一个办法
2. 解决办法 QTextStream *in = new QTextStream(&file); in->setCodec("UTF-8"); QString text = in->readAll(); ui->textEdit->setText(text); 在读取文件之前,设置编码为UTF-8
这样在textEdit里可以正常显示
电脑开机不能进入操作系统界面的故障修复
家里的台式电脑用了大概有三年了,最近这几个月老是出现问题。
最早是系统时间总是被修改,用防修改软件锁定也没有用,过了一阵还是会被修改。通常是这样一个现象,就是如果开机时屏幕出现一个红三角警示,那接下来就会出现时间被修改的情况。
首先怀疑可能是遭到病毒攻击,但经过反复杀毒,并没有解决问题。接着怀疑是主板电池不行了,但是主板电池没弄过,暂时又不愿去动它。后来就在开机出现红三角警示时,直接按F1进入BOSS菜单,将时间设置为正确值,可以正常使用一阵子,但是不能完全消除时间被修改现象。
8月中旬的时候,有一天回到家LD告诉说电脑不能用了。试开机一看,屏幕在提示符状态下出现闪烁的条状光带,无法进入WINDOWS界面。从现象来分析,既然出现闪烁的条状光带,那就不是软件问题而是硬件问题了,而硬件问题最大的可能就是显卡。
根据经验,显卡的问题很多是插接接触不良。于是把网卡拆下来,用橡皮擦把金手指擦干净,反复拔插了几次,问题却还是依然出现。后来想到如果是显卡电路板的问题,除了接触不良外,最有可能的应该是电容,因为电容有容易老化的特性。
再把显卡拿来仔细一看,好家伙,有好几个电容已经爆裂了!
显卡,有四个电容已经明显爆裂开来。
去商场按照参数买了些电容回来,花了13块多。
拿出很久不用的电烙铁,通电加热,开始动工。
拆下来的爆裂电容。
把四个爆裂的电容都换下来了,保险起见有几个还没爆的能换也换成了新电容,有两个难换的就算了。
弄好后把显卡装上,开机,顺利进入操作系统,恢复正常使用。搞掂!哈哈!
本以为这次修好后就不会再有问题,谁知只正常使用了十几天,就又出问题了。现象还是不能进入WINDOWS操作界面,或者刚进入就又退出,试着用最近正确设置和安全状态进入都不成功,但是这次不再有屏幕闪烁和拖线条的情况。
心想显卡刚换过电容,应该不会马上又出问题吧?看到开机时在DOS状态下系统有提示,说找不到某个WINDOWS文件,那应该是操作系统文件损坏了。于是去买了张操作系统盘回来,重装了操作系统,谁知问题照旧,还是进不到WIDDOWS界面。
这下伤脑筋了,想来想去,又想到了主板电池,不是显卡和操作系统的问题,那主板电池的嫌疑就很大了。而且之前多次出现的系统时间被修改(都是改回到2000年*月*日)和上次不能进入操作系统的问题,细究起来也都与主板电池有一定的关系。
于是下决心动动主板电池。打开机箱一看,原来主板电池就在很显眼的地方,试着一板,非常容易就取下来了。还以为很麻烦呢,真是没想到啊没想到!
这个就是主板电池了,标称是3伏的电压。
找出万用表来测量一下。
电压只有2伏,看来电池十有八九是OVER了。
赶紧到附近商店买了一粒电池回来,5块钱。
测一下看
新电池就厉害了,3.5伏!
把新电池装上去,开机一试,顺利进入操作系统,完全恢复正常!大功告成!
这两次花费很少的钱成功解决了电脑硬件的故障,验证了自己维修思路,这是件令人高兴的事。不过高兴之余,还是要反省检讨,应该先检查主板电池就好了,就不至于花冤枉钱买光盘并费了不少时间重装一次操作系统,为此还要重装一些应用软件。
(木木原作 2010年9月20日)
欢迎点击阅读
原标题:Win7系统电脑IPV6无网络访问权限该怎么办?
昨天,小编发布了文章《IPV6为何难以普及,不能使用那就选择关闭协议吧!》,但看苹果,是有不少小伙伴需要使用到的,在探讨中小编也学习了不少,在评论中,有小伙伴提到需要下载IPV6下载资(zi)料(yuan),有小伙伴反馈,自己win7系统电脑ipv6无网络访问权限处,出现这一问题该怎么解决呢?下面小编就分享下具体的解决方法!
方法一:诊断修复
1、电脑在出现IPV6无网络访问权限的情况下,我们可以尝试修复网络连接,点击“诊断”,随后就会出现网络连接问题,如图:
修复:
如果以上方法不能解决问题,那我们接着进行以下操作(方法二)。
方法二:
1、出现诊断解决不了问题时,我们可以先将网络连接禁用再启用,如图:
2、我们还可以Win+R打开快速运行,输入gpedit.msc命令点击回车确定调出本地组策略编辑器,如图:
3、调出后,依照顺序展开“计算机配置-管理模板-系统-Internet 通信管理”,然后我们单击“Internet 通信设置”,在列表中找到“关闭Windows网络连接状态指示器活动测试”并双击,如图:
4、接着在新的窗口中点击勾选“已启用”后确定完成,如图:
完成以上操作即可!
以上便是win7系统电脑IPV6无网络访问权限的解决方法,如果你需要使用但出现相同情况,可按照上面步骤进行操作,小伙伴们也可以收藏下,以备不时之需!电脑需要深度维护或者重装可以选择云骑士装机大师,希望可以帮助到大家!返回搜狐,查看更多
责任编辑:
共京荣开放平台
http://interface.mkstone.club/#/
主要淘宝线报,有凑单、作业图、购买指引、晚安问候等。
配有少量京东、拼多多线报。
9点-10点,大量淘宝线报,23点到00点 大量淘宝线报,00点后大量京东线报。
完全线报血统,人工发单。
线报都是websocket接口
对接方式:
1.链接到线报接口
2.发送任意消息到接口
3.有消息就会给推送了
使用方式:
1.先正则取掉图片,把图片最后处理
(https?)😕/gchat.qpic.cn[-A-Za-z0-9+&@#/%?=_|!:,.;]+[-A-Za-z0-9+&@#/%=_|]?term=2
[emoji=F09F8DAF] [Face174.gif] 这两个是表情,如果匹配不上,也用正则干掉 3.把剩下的就是正常文本了。图片再显示出来就可以了。
全平台混合线报
京东精品线报
球鞋搬砖线报
拼多多水果蔬菜高佣线报
最近准备尝试用VS去开发Qt项目,但是我在ui文件中修改的控件,在vs里面找不到,于是上网浏览解决办法,总结如下
1. 保存Ui文件 在拖拽控件之后,Ctrl+S
2. 重新编译ui文件 3. 右键项目,重新扫描解决方案 这样就可以啦,话说真的好麻烦啊,各位大佬们有没有其他更好的解决办法?在评论区说一下?