• [技术干货] js的相关知识
    1.$(function() {})      $(function() {}) 是jquery里面的一个写法,类似于原生js中的DOMContentLoaded事件。他其实就是$(document).ready(function()的简写。      那么这个函数是在什么时候执行的呢?      他是在DOM加载完毕之后就被执行了的,即页面所有的html标签(包括图片等)都加载完成了,浏览器已经响应完了,所有dom树全部展现到浏览器界面上了(就是各种各样的元素标签),一切准备就绪(其中图片,音视频等这些静态资源等还没加载前)这个函数就开始执行了。2.JSON.stringify()       JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。他的语法是JSON.stringify(value[, replacer[, space]]),其中value为需要转化的数据;replacer是可选项。用于转换结果的函数或数组。如果replacer为函数,则JSON.stringify将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined,则排除成员。根对象的键是一个空字符串:""。如果replacer是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样;space也是一个可选项,是为文本添加缩进、空格和换行符的,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。一般我们使用的JSON.stringify(value)来快速将数据转换为json字符串。3.JSON.parse()      JSON.parse() 方法将数据转换为 JavaScript 对象。他的语法是JSON.parse(text[, reviver]),其中text是必选项, 他必须是一个有效的JSON字符串,如果不是会报错的;reviver是可选项,是一个转换结果的函数, 会为要转换的对象的每个成员调用这个函数。4.JS获取当前网页的相关信息    在WEB开发中,时常会用到javascript来获取当前页面的url网址信息,下面是获取各个部分的小栗子    下面我们举个栗子URL= http://test.com/testPath?parm=123     4.1 window.location.href获取整个URL为字符串           var tem= window.location.href;返回:http://test.com/testPath?parm=123     4.2 window.location.protocol获取 URL 的协议部分           var tem= window.location.protocol; 返回:http:     4.3 window.location.host获取URL的主机部分           var tem= window.location.host;  返回:test.com     4.4 window.location.port获取与URL关联的端口号码           var tem= window.location.port; 返回:空字符(这是因为采用默认的80端口(即使手动添加了:80),那么返回值并不是默认的80而是空字符)     4.5 window.location.pathname获取与URL的路径部分           var tem= window.location.pathname;返回:/testPath     4.6 window.location.search获取 href 属性中跟在问号后面的部分           var tem= window.location.search; 返回:?parm=123      4.7 window.location.hash获取href属性中在"#"后面的参数           var tem= window.location.hash;返回:空字符
  • [交流吐槽] 第三章扩展实验
    # 第三章扩展实验 ## 任务管理: 实例代码: --- ``` #include #include #include #include "ohos_init.h" #include "cmsis_os2.h" osThreadId_t thread1ID;//定义任务ID osThreadId_t thread2ID;//定义任务ID /*****任务一*****/ void thread1(void) { printf("enter thread1\r\n"); osDelay(1);//导致thread1阻塞,thread2运行 printf("thread1 delay done\r\n");//thread1阻塞超时,thread1开始运行,thread2就绪 osThreadSuspend(thread1ID);//挂起thread1 printf("thread1 osThreadResume success\r\n");//在thread2里恢复thread1导致thread1运行,thread2就绪 osThreadTerminate(thread1ID);//删除thread1 printf("Hello\r\n");//删除thread1导致这行命令不能执行 // int sum = 0; // while (1) // { // printf("This is BearPi Harmony Thread1----%d\r\n", sum++); // usleep(1000000); // } } /*****任务二*****/ void thread2(void) { for(int i = 0; i 20; i++){ printf("enter thread2 frequency is %d\r\n", i); } printf("thread1 osThreadSuspend success\r\n");//在thread1里挂起thread1导致thread1阻塞,thread2运行 osThreadResume(thread1ID);//恢复thread1 osThreadTerminate(thread2ID);//删除thread2 printf("World\r\n");//删除thread2导致这行命令不能执行 // int sum = 0; // while (1) // { // printf("This is BearPi Harmony Thread2----%d\r\n", sum++); // usleep(500000); // } } /*****任务创建*****/ static void Thread_example(void) { osThreadAttr_t attr; attr.name = "thread1"; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = 1024 * 4; attr.priority = 25; thread1ID = osThreadNew((osThreadFunc_t)thread1, NULL, &attr);//获取任务ID thread2ID = osThreadNew((osThreadFunc_t)thread2, NULL, &attr);//获取任务ID if (thread1ID == NULL) { printf("Falied to create thread1!\n"); } attr.name = "thread2"; if (thread2ID == NULL) { printf("Falied to create thread2!\n"); } } APP_FEATURE_INIT(Thread_example); ``` --- ## 信号量扩展实验 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/21/1658356632413392330.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/21/1658356644575585614.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20227/21/1658356651726467710.png) ## 软件定时器: 实例讲解(代码版): ``` #include #include #include #include "ohos_init.h" #include "cmsis_os2.h" uint32_t exec1, exec2; /***** 定时器1 回调函数 *****/ void Timer1_Callback(void *arg) { (void)arg; printf("This is BearPi Harmony Timer1_Callback!\r\n"); } /***** 定时器2 回调函数 *****/ void Timer2_Callback(void *arg) { (void)arg; printf("This is BearPi Harmony Timer2_Callback!\r\n"); } /***** 定时器创建 *****/ static void Timer_example(void) { osTimerId_t id1, id2; uint32_t timerDelay; osStatus_t status; exec1 = 1U; id1 = osTimerNew(Timer1_Callback, osTimerOnce, &exec1, NULL);//单次定时器 if (id1 != NULL) { // Hi3861 1U=10ms,100U=1S timerDelay = 100U; status = osTimerStart(id1, timerDelay); if (status != osOK) { // Timer could not be started } } osDelay(50U);//必须小于100U,因为停止定时器函数只能在定时器启动时才能正常工作,而Timer1_Callback单次定时器在100U后自动删除 status = osTimerStop(id1);//停止定时器 if(status != osOK) { printf("stop Timer1 falled\r\n"); } else{ printf("stop Timer1 success\r\n"); } status = osTimerStart(id1, timerDelay);//重启定时器 if (status != osOK) { printf("start Timer1_Callback failed\r\n"); } osDelay(200U);//删除定时器函数无论定时器是否在启动中都可以正常工作 status = osTimerDelete(id1);//删除定时器 if (status != osOK) { printf("Delete Timer1_Callback failed\r\n"); } exec2 = 1U; id2 = osTimerNew(Timer2_Callback, osTimerPeriodic, &exec2, NULL);//循环定时器 if (id2 != NULL) { // Hi3861 1U=10ms,300U=3S timerDelay = 300U; status = osTimerStart(id2, timerDelay); if (status != osOK) { // Timer could not be started } } } APP_FEATURE_INIT(Timer_example) ```
  • [交流吐槽] 任务管理和软件定时器扩展代码
    任务管理:实例讲解(代码版):#include <stdio.h>#include <string.h>#include <unistd.h>#include "ohos_init.h"#include "cmsis_os2.h"osThreadId_t thread1ID;//定义任务IDosThreadId_t thread2ID;//定义任务ID/*****任务一*****/void thread1(void){printf("enter thread1\r\n");osDelay(1);//导致thread1阻塞,thread2运行printf("thread1 delay done\r\n");//thread1阻塞超时,thread1开始运行,thread2就绪osThreadSuspend(thread1ID);//挂起thread1printf("thread1 osThreadResume success\r\n");//在thread2里恢复thread1导致thread1运行,thread2就绪osThreadTerminate(thread1ID);//删除thread1printf("Hello\r\n");//删除thread1导致这行命令不能执行// int sum = 0;// while (1)// {//     printf("This is BearPi Harmony Thread1----%d\r\n", sum++);//     usleep(1000000);// }}/*****任务二*****/void thread2(void){for(int i = 0; i < 20; i++){printf("enter thread2 frequency is %d\r\n", i);    }printf("thread1 osThreadSuspend success\r\n");//在thread1里挂起thread1导致thread1阻塞,thread2运行osThreadResume(thread1ID);//恢复thread1osThreadTerminate(thread2ID);//删除thread2printf("World\r\n");//删除thread2导致这行命令不能执行// int sum = 0;// while (1)// {//     printf("This is BearPi Harmony Thread2----%d\r\n", sum++);//     usleep(500000);// }}/*****任务创建*****/static void Thread_example(void){osThreadAttr_t attr;attr.name = "thread1";attr.attr_bits = 0U;attr.cb_mem = NULL;attr.cb_size = 0U;attr.stack_mem = NULL;attr.stack_size = 1024 * 4;attr.priority = 25;thread1ID = osThreadNew((osThreadFunc_t)thread1, NULL, &attr);//获取任务IDthread2ID = osThreadNew((osThreadFunc_t)thread2, NULL, &attr);//获取任务IDif (thread1ID == NULL)    {printf("Falied to create thread1!\n");    }attr.name = "thread2";if (thread2ID == NULL)    {printf("Falied to create thread2!\n");    }}APP_FEATURE_INIT(Thread_example);软件定时器:实例讲解(代码版):#include <stdio.h>#include <string.h>#include <unistd.h>#include "ohos_init.h"#include "cmsis_os2.h"uint32_t exec1, exec2;/***** 定时器1 回调函数 *****/void Timer1_Callback(void *arg){    (void)arg;printf("This is BearPi Harmony Timer1_Callback!\r\n");}/***** 定时器2 回调函数 *****/void Timer2_Callback(void *arg){    (void)arg;printf("This is BearPi Harmony Timer2_Callback!\r\n");}/***** 定时器创建 *****/static void Timer_example(void){osTimerId_t id1, id2;uint32_t timerDelay;osStatus_t status;exec1 = 1U;id1 = osTimerNew(Timer1_Callback, osTimerOnce, &exec1, NULL);//单次定时器if (id1 != NULL)    {// Hi3861 1U=10ms,100U=1StimerDelay = 100U;status = osTimerStart(id1, timerDelay);if (status != osOK)        {// Timer could not be started        }    }osDelay(50U);//必须小于100U,因为停止定时器函数只能在定时器启动时才能正常工作,而Timer1_Callback单次定时器在100U后自动删除status = osTimerStop(id1);//停止定时器if(status != osOK)    {printf("stop Timer1 falled\r\n");    }else{printf("stop Timer1 success\r\n");    }status = osTimerStart(id1, timerDelay);//重启定时器if (status != osOK)        {printf("start Timer1_Callback failed\r\n");        }osDelay(200U);//删除定时器函数无论定时器是否在启动中都可以正常工作status = osTimerDelete(id1);//删除定时器if (status != osOK)        {printf("Delete Timer1_Callback failed\r\n");        }exec2 = 1U;id2 = osTimerNew(Timer2_Callback, osTimerPeriodic, &exec2, NULL);//循环定时器if (id2 != NULL)    {// Hi3861 1U=10ms,300U=3StimerDelay = 300U;status = osTimerStart(id2, timerDelay);if (status != osOK)        {// Timer could not be started        }    }}APP_FEATURE_INIT(Timer_example);
  • [技术干货] 编译fio报static declaration of ‘gettid’ follows non-static错误解决方法
    【问题描述】编译fio过程报error: static declaration of ‘gettid’ follows non-static declaration问题,详细报错如下:In file included from os/os.h:31,                 from thread_options.h:5,                 from fio.h:19,                 from gettime.c:10:os/os-linux.h:108:19: error: static declaration of ‘gettid’ follows non-static declaration  108 | static inline int gettid(void)      |                   ^~~~~~In file included from /usr/include/unistd.h:1204,                 from gettime.c:5:/usr/include/bits/unistd_ext.h:34:16: note: previous declaration of ‘gettid’ was here   34 | extern __pid_t gettid (void) __THROW;      |                ^~~~~~make: *** [Makefile:225: gettime.o] Error 1ERROR: excute "make" failed, please check it.【解决方法】修改os/os-linux.h文件将第108行的static inline int gettid(void)修改为static inline int sys_gettid(void)再次执行make编译即可
  • [问题求助] 在遍历填入表格数据时,如何动态的将值放到html的指定id 进行拼接 比如占位符之类的字符?
    【功能模块】【操作步骤&问题现象】1、2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] Chrome浏览器打开文件类型的html网页,Studio无法录制拾取
    解决方法:1. 打开chrome浏览器,访问 chrome://extensions/2. 找到weautomate浏览器插件,单击“详细信息”。3. 单击开启“允许访问文件网址”。4. 关闭重启浏览器注:浏览器插件未安装成功,请参考如下链接文档手动安装插件https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=181670
  • [技术干货] 反向代理服务器搭建
    反向代理服务器对外的表现是Web服务器,其主要的技术就是地址转换。通过反向代理,客户端计算机无需任何设置就可以使用数字资源。反向代理技术中每个Web服务器现代感与反向代理服务器的某个目录。反向代理可以把服务器的目录映射在需要进行代理的服务器上。但是,这种设置只能解决用户一次访问出现的问题,无法让用户借助反向代理连续访问。因此,必须借助正规表达式检测、替换所用的链接,达到借助反向代理实现连续访问的效果借助反向代理技术构建Web缓存,从而提升Web站点自身的安全性及访问速度。采用反向代理设置在原服务器前端,配备较大容量的内存及高速磁带,缓存用户的请求。反向代理服务器可以访问用户的源地址,从而拒绝非法用户恶意骚扰和访问。依据实现设置的控制策略及用户表或IP地址控制参数达到合理控制的目的。访问控制模式可根据服务器控制策略、IP地址等参数掌控代理服务器和Web资源控制系统的记录。用户源地址信息可采用accept函数获取,可以借助getpeername函数获得。进行配置文件时,把拒绝IP地址全部罗列出来,在启动反向代理服务器时读入其中,随之把用户源IP地址与列表内的地址进行比较,如果相同则拒绝该用户访问。为了节约内存并提升网速,对于IP地址列表使用子网/子网掩码的结构,从而使用子网/子网掩码对源IP地址进行连续性描述。因部分服务器无法合理管理用户控制和访问数,极易出现盗用信息资源的情况。
  • [技术干货] 保存网页到html文件
    详情代码见“get_html_to_local.rar”
  • [技术干货] 中添加监听句柄的方式
    这篇文章主要介绍了JavaScript中添加监听句柄的方式,监听就是触发某事件之后做出的响应,监听句柄是触发某相应的条件,下面关于添加监听句柄的方式的详细内容,需要的朋友可以参考一下,希望对你有所帮助目录• 一、效果展示 • 二、句柄合集 • 三、添加监听的方式 • 1.将事件与函数绑定在一起 • 2.先获取元素再添加事件 前言:监听就是触发某事件之后做出的响应,监听句柄是触发某相应的条件一、效果展示鼠标聚焦、鼠标移开、鼠标点击等等都可以作为监听句柄二、句柄合集•     onchange    HTML 元素改变•     onclick    用户点击 HTML 元素•     onmouseover    用户在一个HTML元素上移动鼠标•     onmouseout    用户从一个HTML元素上移开鼠标•     onkeydown    用户按下键盘按键•     onload    浏览器已完成页面的加载•     onclick 失去焦点•     onfocuse 获取焦点三、添加监听的方式添加监听的方式有两种:1.将事件与函数绑定在一起• 例如将点击监听句柄与f1函数绑定起来1234567891011121314151617181920212223242526<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title></head><body>    <script>        function f1()        {            element=document.getElementById("myimage")            if(element.src.match("bulbon"))            {                element.src="../pic_bulboff.gif"            }            else{                element.src="../pic_bulbon.gif"            }        }    </script>    <img id="myimage" src="../pic_bulboff.gif" onclick="f1()" alt="" width="100" height="150">    <p>点击灯泡开关灯</p></body></html>2.先获取元素再添加事件例如:12           var x = document.getElementById("myBtn");        x.addEventListener("mouseover", myFunction);将鼠标覆盖句柄与函数myFunction绑定在一起12345678910111213141516171819202122232425262728293031323334353637<!DOCTYPE html><html><head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title> </head>    <body>            <p>实例使用 addEventListener() 方法在同一个按钮中添加多个事件。</p>            <button id="myBtn">点我</button>            <p id="demo"></p>    <script>            var x = document.getElementById("myBtn");            x.addEventListener("mouseover", myFunction);            x.addEventListener("click", mySecondFunction);            x.addEventListener("mouseout", myThirdFunction);            function myFunction() {                document.getElementById("demo").innerHTML += "Moused over!<br>"            }            function mySecondFunction() {                document.getElementById("demo").innerHTML += "Clicked!<br>"            }            function myThirdFunction() {                document.getElementById("demo").innerHTML += "Moused out!<br>"            }            // 监听函数如何传递参数            document.getElementById("myBtn").addEventListener("click", function() {                myFunction(p1, p2);            });            function myFunction(a, b) {                 var result = a * b;                 document.getElementById("demo").innerHTML = result;            }    </script>     </body></html>总结:两种监听方式均可以达到效果,个人认为先获取后添加的句柄监听使用更为方便。原文链接:https://blog.csdn.net/apple_51931783/article/details/122767934
  • [其他] 【扩容】扩容14%失败
    问题现象:扩容14%失败问题分析:1.登录后台数据库,获取FAIL的jobidSelect task.* from taskmgr_task as task left outer join taskmgr_job as job on job.job_id = task.job_id where job.request like '%{clusterName}%' order by job_id, task_index asc;2.登录两个dwscontroller容器查看日志,用jobId过滤vpc:xxxxxxxx is not belong to this user.3.分析vpcid来源于原有节点的vpcId,是创建时使用用户,所以创建时和扩容时账户不一致,当前账户的projectid和当前集群的vpc不对等问题根因:用户权限不一致,建议使用创建集群的用户进行扩容恢复方案:1.找回原有创建时使用的用户,用此用户进行扩容寻找方法:1)在rds_cluster中获取userid2)用bssadmin管理员登录运营面,选择组织,点击用户管理,查看对应的而用户2.修改失败节点状态300为400,再次扩容update rds_instance  set status=400 where status=3003.使用原来的用户进行扩容
  • [API集成编排] 卡片中的HTML面板支持国际化吗,如果支持应该是怎么写
    【操作步骤&问题现象】卡片中的HTML面板支持国际化吗,如果支持应该是怎么写
  • [页面编排] 2.0环境HTML面板数据加载不出来
    问题:代码使用{{#each results}}无法加载出数据
  • [技术干货] JS 实现密码强度验证【不写代码浑身难受】
    在网络服务中,为了保护用户私密信息,会要求用户输具有一点安全几级别的密码,这样为了防止他人盗用,例如:一些游戏账号的,如果输入纯6位数字和6为字符就会提示强度太低,要求重新输入,一般计算密码强度验证的方式都是计算字符,然后分类加权重。权重越高相应的强度越高。 //设置提示文字颜色 function setColor(_this, cssOption) { //判断节点类型(防止我们传的节点类型是 空 || 文本 || 注释 || 文本节点(非htmL元素)) if (!_this || _this.nodeType === 3 || _this.nodeType === 8 || !_this.style) { return } for (var cs in cssOption) { _this.style[cs] = cssOption[cs] } return _this } //检测密码强度(第一个参数时密码框,第二个参数是显提示文字) function pwdstrength(pwdStrength, showStrength) { const self = this pwdStrength.onkeyup = function() { //按键抬起就去判断确认密码和密码时候样一致 inconsistent.className = (pwd.value === confimpwd.value) ? 'hidden' : 'show' let _color = ['red', 'yellow', 'orange', 'green'] let tipmess = ['密码太短', '弱', '中', '强'] _strength = 0 //密码强度值 _v = pwd.value.trim() _vL = _v.length //获取强度值 let charStrength = function(char) { //数字 if (char >= 48 && char <= 57) { return 1 } if (char >= 97 && char <= 122) { //小写 return 2 } else { return 3 } } //密码长度小于6个字符 显示密码太短 if (_vL < 6) { showStrength.innerText = tipmess[0] setColor(showStrength, { 'color': _color[0] }) } else { for (let i = 0; i < _vL; i++) { _strength += charStrength(_v.toLowerCase().charCodeAt(i)) } if (_strength < 10) { //强度小于10 showStrength.innerText = tipmess[1] setColor(showStrength, { 'color': _color[1] }) } if (_strength >= 10 && _strength <= 15) { //强度小于10 showStrength.innerText = tipmess[2] setColor(showStrength, { 'color': _color[2] }) } if (_strength > 15) { //强度小于10 showStrength.innerText = tipmess[3] setColor(showStrength, { 'color': _color[3] }) } } } }上面就是实现功能的核心代码:代码说明: setColor(_this,cssOption) 来配置显示强度文字的样式,第一个参数接收是目标元素(html) 第二个参数接收的是一个对象通过 for  in 来拿到属性与属性值。pwdstrength(pwdStrength, showStrength)pwdStrength接收参数是操作目标 showStrength参数是显示文字样式强度计算规则:字符权重 :  数字 1  字母2   其他字符为 3  当密码长度小于6显示不合格(可以做样式提示)当字符长度>=6 强度小于 10 强度  ’弱‘当字符长度>=10 强度小于 15 强度 ’中‘当字符长度>=15  强度 ’强‘
  • [技术干货] HTML5 WebSocket技术使用详解
    WebSocketWebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客服端的浏览器,这种方式有一个很大的弊端,就是会占用很多的带宽。最新的轮询效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求。使用WebSocket,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,两者之间就直接可以数据互相传送。而且它为我们实现即时服务带来了两大好处:节省资源:互相沟通的Header是很小的-大概只有 2 Bytes。推送信息:不需要客户端请求,服务器可以主动传送数据给客户端。socket.ioSocket.IO是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。socket.io的特点易用性:socket.io封装了服务端和客户端,使用起来非常简单方便。跨平台:socket.io支持跨平台,这就意味着你有了更多的选择,可以在自己喜欢的平台下开发实时应用。自适应:它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5。WebSocket 安装部署1npm install socket.io服务监听socket.io的服务端启动非常的简单,引用socket.io模块。1var io = require('socket.io');然后调用listen函数,传入监听的端口号,开始服务监听。启用了80端口用于测试:1var io = require('socket.io')(80);注册事件12345io.on('connection', function (socket) {  socket.on('disconnect', function () {   })})connection事件在客户端成功连接到服务端时触发,有了这个事件,我们可以随时掌握用户连接到服务端的信息。当客户端成功建立连接时,在connection事件的回调函数中,我们还是可以为socket注册一些常用的事件,如:disconnect事件,它在客户端连接断开是触发,这时候我就知道用户已经离开了。WebSocket 启动服务目前为止,我们已经搭建好了一个最简单的socket服务器,为了在浏览器中能够访问到我们的服务,我们还需要在服务端搭建一个简单的web服务器,让浏览器能够访问我们的客户端页面。为了便捷,我们选用node.js中常用的express框架来实现web服务,示例如下:1234567891011var express = require('express');var app = express();app.get('/', function (req, res) {  res.status(200).send('成功连接!')});var server = require('http').createServer(app);var io = require('socket.io')(server);io.on('connection', function (socket) { });server.listen(80);WebSocket 客户端引用服务端构建完毕,下面看一看客户端应该如何使用。服务端运行后会在根目录动态生成socket.io的客户端js文件,客户端可以通过固定路径/socket.io/socket.io.js添加引用。首先添加网页index.html,并在网页中引用客户端js文件:1<script src="//cdn.bootcss.com/socket.io/2.0.2/socket.io.js"></script>WebSocket 连接服务当客户端成功加载socket.io客户端文件后会获取到一个全局对象io,我们将通过io.connect函数来向服务端发起连接请求。1234567var socket = io.connect('/');socket.on('connect',function(){  //连接成功});socket.on('disconnect',function(data){  //连接断开});connect函数可以接受一个url参数,url可以socket服务的http完整地址,也可以是相对路径,如果省略则表示默认连接当前路径。与服务端类似,客户端也需要注册相应的事件来捕获信息,不同的是客户端连接成功的事件是connect。了解了客户端如何使用,下面我们创建网页index.html,并添加如下内容(保存):123456789101112131415<html><head>  <script src="//cdn.bootcss.com/socket.io/2.0.2/socket.io.js"></script>  <script>    window.onload = function(){      var socket = io.connect('/');      socket.on('connect',function(){        document.write('连接成功!');      });    };  </script></head><body></body></html>页面添加完毕还要记得在服务端app.js中为它添加路由,让我们可以访问测试网页:123app.get('/index',function(req,res){  res.sendFile('index.html',{root:__dirname});});WebSocket 实时通讯服务端和客户端都构建完毕了,下面开始发送消息。当我们成功建立连接后,我们可以通过socket对象的send函数来互相发送消息,示例-客户端向服务端发送消息(index.html):12345678var socket = io.connect('/');socket.on('connect',function(){  //客户端连接成功后发送消息'hello world!'  socket.send('hello world!');});socket.on('message',function(data){  alert(data);});连接成功后,我们向服务端发送消息hello world!,还为socket注册了message事件,它是send函数对应的接收消息的事件,当服务端向客户端send消息时,我们就可以在message事件中接收到发送过来的消息。服务端向客户端发送消息也可以通过send的方式,示例 - 服务端向客户端发送消息(app.js):1234567var io = require('scoket.io');io.on('connection', function (socket) {  socket.send('Hello World!');  socket.on('message', function (data) {    console.log(data);  })});与客户端相同,服务端也需要为socket注册message事件来接收客户端发送过来的消息。WebSocket 发送信息socket.io既然是用来实现通讯的,那么如何发送、接收信息才是根本。在socket.io中,emit函数用于发送数据,我们使用send的方式实现了信息的互发,其实send函数只是emit的封装,实际上还是使用了emit,且看send函数是如何实现的:123456function send(){ var args = toArray(arguments); args.unshift('message'); this.emit.apply(this, args); return this;}在send函数中,获取到原来的参数,并在原来的基础上插入了一个参数message,然后调用了emit函数。通过send函数的实现,我们也学会了emit函数的用法,它有多个参数,第一个参数是事件名称,在接收端注册该事件就可以接收到发送过去的信息,事件名称可以自由定义,在不同的场景下,我们可以定义不同的事件来接收消息。第二个参数才是发送的数据。了解清楚了工作原理,下面来将send替换成emit函数发送信息:123456//app.jsio.on('connection',function(socket){   socket.emit('message','连接成功!');   socket.on('message',function(data){  });});WebSocket 服务端事件事件监听是实现通讯的基础,因此充分了解socket.io的事件,学习如何在正确的时候使用它们至关重要。在一些关键的的状态下,socket.io可以注册相应的事件,通过事件监听,我们可以在这些事件中作出反应,常用的事件如下:connection——客户端成功连接到服务器。message——捕获客户端send信息。。disconnect——客户端断开连接。error——发生错误。WebSocket 客户端较服务端而言,客户端提供更多的监听事件,在实时应用中,我们可以为这些事件注册监听并作出反应,例如:connect提示用户连接成功,disconnect时提示用户停止服务等等。connection——成功连接到服务器。connecting——正在连接。disconnect——断开连接。connect_failed——连接失败。error——连接错误。message——监听服务端send的信息。reconnect_failed——重新连接失败。reconnect——重新连接成功。reconnecting——正在重连。那么客户端socket发起连接时的顺序是怎么样的呢?当第一次连接时,事件触发顺序为: connecting → connect;当失去连接时,事件触发顺序为:disconnect → reconnecting → connecting → reconnect → connect。WebSocket 命名空间命名空间着实是一个非常实用好用的功能。我们可以通过命名空间,划分出不同的房间,在房间里的广播和通信都不会影响到房间以外的客户端。那么如何创建房间呢?在服务端,通过of("")的方式来划分新的命名空间:12io.of('chat').on('connection',function(socket){});示例中,我们创建一个名为chat的房间,客户端可以通过如下方式连接到指定的房间:1var socket = io.connect('/chat');虽然连接到指定的房间,但是我们也可以在服务端操作,自由的进出房间:12socket.join('chat');//进入chat房间socket.leave('chat');//离开chat房间WebSocket 广播消息在实时应用中,广播是一个不可或缺的功能,socket.io提供两种服务端广播方式。第一种广播方式可以称之为'全局广播',顾名思义,全局广播就是所有连接到服务器的客户端都会受到广播的信息:1socket.broadcast.emit('DATA',data);但是,在实际应用场景中,我们很多时候并不需要所有用户都收到广播信息,有的广播信息只发送给一部分客户端,比如某个房间里面的用户,那么可以使用如下方式:1socket.broadcast.to('chat').emit('DATA',data);中间件socket.io提供中间件功能,我们可以通过中间件来对请求进行预处理,比如身份验证:1234io.use(function(socket, next){ if (socket.request.headers.cookie) return next(); next(new Error('Authentication error'));});示例中展示了通过中间件进行身份验证,当没有cookie的时候抛出异常。传递参数在很多应用场景中,客户端发起连接请求时都需要传递参数,这些参数可能是身份验证、初始化设置等等,那么socket.io发起连接时如何传递参数呢?1var socket = io.connect('/');由于connect函数发起连接的参数是一个url,你可能会想到把参数拼接到url上,如http://xxxx?xx=xxxx,但是很遗憾这样是行不通的,我们可以通过这样的方式来传递参数:1var socket = io.connect('/',{ _query:'sid=123456' });在服务端可以这样获取到传递的参数:1234io.use(function(socket){   var query = socket.request._query;   var sid = query.sid; });客户端传递的参数已经被解析成了一个json对象,这个对象就是_query。
  • [问题求助] 建站后可以上传自己已经做好的html页面吗?
    如题。比如说我用其它的一些网页编辑软件做好一个html页面,同时还生成了一些css,js文件这样的,可以把这些一起上传然后作为网站里的一个页面吗?谢谢。