牛客面经每日一总结(一)

简介: 牛客面经每日一总结(一)

webSoket


WebSocket”是一种基于 TCP 的轻量级网络通信协议,在地位上是与 HTTP“平级”的。


其实 WebSocket 与 HTTP/2 一样,都是为了解决 HTTP 某方面的缺陷而诞生的。


HTTP/2 针对的是“队头阻塞”,而 WebSocket 针对的是“请求 - 应答”通信模式。

那么,“请求 - 应答”有什么不好的地方呢?


“请求 - 应答”是一种 “半双工” 的通信模式,虽然可以双向收发数据,但同一时刻只能一个方向上有动作,传输效率低。更关键的一点,它是一种“被动”通信模式,服务器只能“被动”响应客户端的请求,无法主动向客户端发送数据。


webSocket的特点


WebSocket 是一个真正“全双工” 的通信协议,与 TCP 一样,客户端和服务器都可以随时向对方发送数据,而不用像 HTTP“你拍一,我拍一”那么“客套”。于是,服务器就可以变得更加“主动”了。一旦后台有新的数据,就可以立即“推送”给客户端,不需要客户端轮询 ,“实时通信”的效率也就提高了


WebSocket 采用了二进制帧结构,语法、语义与 HTTP 完全不兼容。


服务发现方面,WebSocket 没有使用 TCP 的“IP 地址 + 端口号” ,而是延用了 HTTP 的 URI 格式,但开头的协议名不是“http” ,引入的是两个新的名字: “ws”和“wss” ,分别表示明文和加密的 WebSocket 协议。


WebSocket 的默认端口也选择了 80 和 443,因为现在互联网上的防火墙屏蔽了绝大多数的端口,只对 HTTP 的 80、443 端口“放行”,所以 WebSocket 就可以“伪装”成 HTTP 协议,比较容易地“穿透”防火墙,与服务器建立连接。


WebSocket 的握手


和 TCP、TLS 一样,WebSocket 也要有一个握手过程,然后才能正式收发数据。


WebSocket 的握手是一个标准的 HTTP GET 请求,但要带上两个协议升级的专用头字段:


  • “Connection: Upgrade”,表示要求协议“升级”;


  • “Upgrade: websocket”,表示要“升级”成 WebSocket 协议。


另外,为了防止普通的 HTTP 消息被“意外”识别成 WebSocket,握手消息还增加了两个额外的认证用头字段


  • Sec-WebSocket-Key:一个 Base64 编码的 16 字节随机数,作为简单的认证密钥;


  • Sec-WebSocket-Version:协议的版本号,当前必须是 13。


服务器收到 HTTP 请求报文,看到上面的四个字段,就知道这不是一个普通的 GET 请求,而是 WebSocket 的升级请求,于是就不走普通的 HTTP 处理流程,而是构造一个特殊的“101 Switching Protocols”响应报文,通知客户端,接下来就不用 HTTP 了,全改用 WebSocket 协议通信。(有点像 TLS 的“Change Cipher Spec”)。


浏览器是一个“沙盒”环境,有很多的限制,不允许建立 TCP 连接收发数据而有了 WebSocket,我们就可以在浏览器里与服务器直接建立“TCP 连接” ,获得更多的自由。


不过自由也是有代价的,WebSocket 虽然是在应用层,但使用方式却与“TCP Socket”差不多,过于“原始”,用户必须自己管理连接、缓存、状态,开发上比 HTTP 复杂的多,所以是否要在项目中引入 WebSocket 必须慎重考虑。


总结:


  • HTTP 的“请求 - 应答”模式不适合开发“实时通信”应用,效率低,难以实现动态页面,所以出现了 WebSocket;


  • WebSocket 是一个“全双工”的通信协议,相当于对 TCP 做了一层“薄薄的包装”,让它运行在浏览器环境里;


  • WebSocket 使用兼容 HTTP 的 URI 来发现服务,但定义了新的协议名“ws”和“wss”,端口号也沿用了 80 和 443;


  • WebSocket 使用二进制帧,结构比较简单,特殊的地方是有个“掩码”操作,客户端发数据必须掩码,服务器则不用;


  • WebSocket 利用 HTTP 协议实现连接握手,发送 GET 请求要求“协议升级”,握手过程中有个非常简单的认证机制,目的是防止误连接。


思考题


1.WebSocket 和 HTTP/2 都是用来弥补HTTP协议的一些缺陷和不足。


WebSocket 主要解决双向通信、全双工问题,HTTP/2 主要解决传输效率的问题,两者在二进制帧的格式上也不太一样,HTTP/2 有多路复用、优先级和流的概念。


2.试着自己解释一下 WebSocket 里的”Web“和”Socket“的含义。


Web就是HTTP的意思,Socket就是网络编程里的套接字,也就是HTTP协议上的网络套接字,可以任意双向通信。


3.结合自己的实际工作,你觉得 WebSocket 适合用在哪些场景里?


IM通信,实时互动,回调响应,数据实时同步。


css选择器优先级


可以通过数值来指定权重。


!important表示无穷大


内联:1000


id:100


类:10


标签:1


通配符、子类选择器、兄弟选择器,如*, >, +,权值为0


继承的样式没有权值


z-index层叠上下文


用来确定元素在z轴的排列顺序。


页面是个二维平面,但是层叠上下文能够让 HTML 元素具有三维概念,这些 HTML 元素按照自身属性的优先级分布在垂直于这个二维平面的 z 轴上。


在层叠上下文中,子元素同样也按照上面解释的规则进行层叠。 重要的是,其子级层叠上下文的 z-index 值只在父级中才有意义。子级层叠上下文被自动视为父级层叠上下文的一个独立单元。


  • 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级。


  • 每个层叠上下文都完全独立于它的兄弟元素:当处理层叠时只考虑子元素。


  • 每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按顺序进行层叠。


那么那些css属性会形成一个层叠上下文呢?


  • 文档根元素(<html>);


  • position值为 absolute(绝对定位)或  relative(相对定位)且 z-index值不为 auto 的元素;


  • position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持);


  • flex 容器的子元素,且 z-index值不为 auto


  • grid 容器的子元素,且 z-index值不为 auto


  • opacity属性值小于 1 的元素


  • mix-blend-mode 属性值不为 normal 的元素;


  • 以下任意属性值不为 none 的元素:


  • transform


  • filter


  • backdrop-filter


  • perspective


  • clip-path


  • mask, mask-image,mask-border


  • isolation 属性值为 isolate 的元素;


  • will-change值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素。


  • contain 属性值为 layoutpaint 或包含它们其中之一的合成值(比如 contain: strictcontain: content)的元素。比对层叠权重时,只能是兄弟之间比较,不能是这个元素的子元素和那个元素比较。要么都是父元素要么都是子元素比较。


网络异常,图片无法展示
|


画三角形的方法


通过边框,设置其他边框颜色为transparent。


div {
      border-left: 10px solid skyblue;
      border-right: 10px solid transparent;
      border-bottom: 10px solid transparent;
      border-top: 10px solid transparent;
    }


网络异常,图片无法展示
|


通过canvas


通过transform: rotate(45deg);


/* parent */
    .parent {
      width: 100px;
      height: 50px;
      background: red;
      position: relative;
    }
    .son {
      position: absolute;
      left: 50%;
      bottom: 0;
      margin-top: 50%;
      width: 20px;
      height: 20px;
      background: red;
      transform: rotate(45deg);
    }
  <!-- 利用两个元素叠加,旋转小元素 -->
  <div class="parent">
    <div class="son"></div>
  </div>


网络异常,图片无法展示
|


数组去重


  • 通过Set的特点


  • 通过对象键值相互覆盖。


提到了map,map是什么数据类型


map就是保存键值对的数据结构。他主要是为了弥补js对象键值只能是字符串类型,不能是其他类型的不足。


map接收具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构。


内部还提供了多种操作键,值的api。


  • set(key, value)


  • get(key)


  • clear()


  • size


  • has(key)


  • delete(key)


  • 遍历的方法


  • Map.prototype.keys():返回键名的遍历器。


  • Map.prototype.values():返回键值的遍历器。


  • Map.prototype.entries():返回所有成员的遍历器。


  • Map.prototype.forEach():遍历 Map 的所有成员。


map和object区别


  • map可以使用for of遍历。因为Map 结构的默认遍历器接口(Symbol.iterator属性),就是entries方法。但是object不可以


  • map的键可以是任意类型。但是object的键只能是字符串类型。


indexOf


字符串,数组都具有该方法,主要是返回指定元素的下标。


ES6了解多少


es6的语法基本都了解。比如


  • Object.is()。主要是解决===的问题的。NaN !== NaN, +0 === -0


  • 引入块级作用域let, const


  • 对于函数引入默认参数,剩余参数,并且还定义了箭头函数来解决this指向问题。


  • 引入模板字符串,来解决常规字符串的不足。


  • 将一些方法绑定在Number,让其不作为全局函数。比如Number.isNaN, Number.isFinite, Number.parseInt, Number.parseFloat


  • 对数组增加一些遍历方法。entries(),keys() 和 values(),他们都返回遍历器对象。增加includes()来查找元素是否存在,替代了indexOf方法。indexOf方法内部是调用===做判断的,所以对于NaN会出错。


  • 增加了class语法,让js书写类更友好。


  • 对于对象增加了获取对象元素的方法。Object.keys(),Object.values(),Object.entries()。都返回一个数组。


  • promise


  • proxy


  • symbol,引入一个创建唯一值的类型


  • async await等等


addEventListener参数,第三个参数是什么作用


请参考mdn第三个参数可以是一个配置对象,也可以是一个boolean值。


boolean默认是为false


  • true: 表示触发事件的方式是捕获方式


  • false:表示触发事件的方式是冒泡方式 配置对象


  • capture:  Boolean,表示 listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发。


  • once:  Boolean,表示 listener 在添加之后最多只调用一次。如果是true,listener 会在其被调用之后自动移除。


  • passive: Boolean,设置为true时,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。


  • signalAbortSignal,该 AbortSignalabort() 方法被调用时,监听器会被移除。


什么是事件委托


事件委托就是把事件绑定到父元素上,当操作子元素时,由于浏览器的事件冒泡机制,就触发了父元素上的事件,从而达到同样的效果。


这里先来区分两个对象吧


  • currentTarget。表示当前绑定事件的元素。


  • target。表示触发事件的元素。


事件委托的优点


  • 绑定事件越多,浏览器内存占用越大,严重影响性能。所以减少内存消耗。



Promise几种状态


三种状态


  • 成功 resolved


  • 失败 rejected


  • 未处理 pending


Promise.all了解吗,返回的结果有什么特点,这个数组有什么特点?


如果传入的promises状态都变为resolved,那么promise的状态变为resolved,它将结果放在一个数组中返回。如果传入的promises状态变为rejected,那么promise的状态变为rejected。


成功时,返回的结果,会按照注册的先后顺序存入数组。


HTTP请求方法


  • GET: 获取资源,可以搭配URI和其他头字段完成对资源更精细的操作。


  • HEAD:获取资源的元信息(即响应头)。服务器不返回实体部分。主要用于检查资源是否存在,资源是否更新。


  • POST:向资源提交数据,相当于写入或上传数据。


  • PUT:类似 POST。但是是更新资源。


  • DELETE:请求服务器删除指定的资源。不存在验证机制,不安全。


  • CONNECT:要求服务器为客户端和另一台远程服务器建立特殊的连接隧道。此时web服务器充当代理的角色


  • OPTIONS:列出可对资源实行的操作方法。


  • TRACE:追踪请求 - 响应的传输路径。多用于对http链路的测试和诊断。 存在XST漏洞。


什么情况下会options


想让服务器返回当前允许请求的动作,或者携带的请求头。


  • OPTIONS 请求与 HEAD 类似,一般也是用于客户端查看服务器的性能。


  • 这个方法会请求服务器返回该资源所支持的所有 HTTP 请求方法,该方法会用'*'来代替资源名称,向服务器发送 OPTIONS 请求,可以测试服务器功能是否正常。


  • JS 的 XMLHttpRequest对象进行 CORS 跨域资源共享时,对于复杂请求,就是使用 OPTIONS 方法发送嗅探请求,以判断是否有对指定资源的访问权限。


讲一下预检请求,预检成功返回的状态码是什么?


对于跨域资源访问的时候,我们发送非简单请求,那么浏览器首先自动给我们发送一个options请求,用来确认我们发送的动作或者头部字段,服务器是否允许。


204 not content


介绍CORS


请查看mdn


就是一个用于跨域资源访问的技术。


服务器端用来配置一些响应字段,来控制那些域可以访问,那么方法可以操作,那么头部字段可以携带。


  • 简单请求 请求方法只能是:get, post, head


请求头部只能携带


-   `Accept`
-   `Accept-Language`
-   `Content-Language`
-   `Content-Type` 的值仅限于下列三者之一:
    -   `text/plain`
    -   `multipart/form-data`
    -   `application/x-www-form-urlencoded`


  • 非简单请求 不满足简单请求的条件就会触发非简单请求。


他首先会发送一个options请求,用来确认当前请求是否被允许。根据access-control-allow-headers, access-control-allow-methods来确认。


跨域方法有哪些


  • jsonp


  • cors


  • webpack代理(只能在开发阶段)


  • nodejs代理


HTTP状态码有哪些


  • 1××:提示信息,表示目前是协议处理的中间状态,还需要后续的操作;


  • 2××:成功,报文已经收到并被正确处理;


  • 3××:重定向,资源位置发生变动,需要客户端重新发送请求;


  • 4××:客户端错误,请求报文有误,服务器无法处理;


  • 5××:服务器错误,服务器在处理请求时内部发生了错误。


一些常见状态码


101 Switching Protocols。它的意思是客户端使用 Upgrade 头字段,要求在 HTTP 协议的基础上改成其他的协议继续通信,比如 WebSocket。而如果服务器也同意变更协议,就会发送状态码 101,但这之后的数据传输就不会再使用 HTTP 了。


204 No Content。它的含义与“200 OK”基本相同,但响应头后没有 body 数据。


206 Partial Content。只返回部分内容。http断点续传。


202 Accepted。已接受请求,但是未处理完成。


301 Moved Permanently。永久移动,请求的资源已被永久移动到新的URI,location字段将指定新的URI,浏览器会自动定向到新的URI,今后请求都使用新的URI。


302 Found。临时移动,只是临时移动资源,下次请求依旧继续使用原URI。


304 Not Modified。 它用于 If-Modified-Since 等条件请求,表示资源未修改,用于缓存控制。它不具有通常的跳转含义,但可以理解成“重定向已到缓存的文件”(即“缓存重定向”)。


405 Method Not Allowed:不允许使用某些方法操作资源,例如不允许 POST 只能 GET。


406 Not Acceptable:资源无法满足客户端请求的条件,例如请求中文但只有英文。


408 Request Timeout:请求超时,服务器等待了过长的时间。


409 Conflict:多个请求发生了冲突,可以理解为多线程并发时的竞态。


413 Request Entity Too Large:请求报文里的 body 太大。


414 Request-URI Too Long:请求行里的 URI 太大。


429 Too Many Requests:客户端发送了太多的请求,通常是由于服务器的限连策略。


431 Request Header Fields Too Large:请求头某个字段或总体太大。


403 Forbidden。服务器理解请求客户端的请求,但是拒绝执行请求。


404 Not found。服务器无法根据客户端的请求找到资源。


404 Bad Request。客户端请求语法错误,服务器不能理解。则是一个通用客户端错误,应该避免使用他。


401 Unauthorized。请求邀请用户的身份认证。


503 Service Unavailable。 表示服务器当前很忙,暂时无法响应服务,503 响应报文里通常还会有一个“Retry-After”字段,指示客户端可以在多久以后再次尝试发送请求。


500 Internal Server Error。服务器内部错误,无法完成请求。


502 Bad Gateway 是一种HTTP协议的服务器端错误状态代码,它表示作为网关或代理角色的服务器,从上游服务器(如tomcat、php-fpm)中接收到的响应是无效的。


TCP 和 UDP


TCP:


  • 面向连接


  • 面向字节流, 是指保证数据完整。


  • 有状态


  • 保证可靠交付, 是指保证数据不丢失。


  • 具备拥塞控制


  • 点对点传播


  • 有序(TCP 引入了数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件。)


UDP:


  • 无连接


  • 面向数据报


  • 无状态


  • 不保证可靠交付


  • 不具备拥塞控制


  • 广播、多播


  • 无序


线程 VS 进程


线程是不能单独存在的,它是由进程来启动和管理的。


一个进程就是一个程序的运行实例。详细解释就是,启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。


  • 进程中的任意一线程执行出错,都会导致整个进程的崩溃。


  • 线程之间共享进程中的数据。


  • 当一个进程关闭之后,操作系统会回收进程所占用的内存。


  • 进程之间的内容相互隔离。


浏览器的发展


单进程


单进程浏览器是指浏览器的所有功能模块都是运行在同一个进程里,这些模块包含了网络、插件、JavaScript 运行环境、渲染引擎和页面等。


从而导致单进程浏览器不稳定、不流畅和不安全。


  • 不稳定。插件,渲染引擎模块都不是很稳定,任何一个线程挂了,都会导致整个浏览器挂掉。


  • 不流畅。所有页面的渲染模块、JavaScript 执行环境以及插件都是运行在同一个线程中的,这就意味着同一时刻只能有一个模块可以执行。如果js脚本执行时间过长,就会造成页面卡顿。


  • 不安全。通过插件可以获取到操作系统的任意资源,当你在页面运行一个插件时也就意味着这个插件能完全操作你的电脑。如果是个恶意插件,那么它就可以释放病毒、窃取你的账号密码,引发安全性问题。


多进程


网络异常,图片无法展示
|


Chrome 的页面是运行在单独的渲染进程中的,同时页面里的插件也是运行在单独的插件进程之中,而进程之间是通过 IPC 机制进行通信。从而解决了上述单进程浏览器的问题。


最新浏览器包括:


1 个浏览器(Browser)主进程、1 个 GPU 进程、1 个网络(NetWork)进程、多个渲染进程和多个插件进程。


  • 浏览器进程。主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。


  • 渲染进程。核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。


  • GPU 进程。其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程。


  • 网络进程。主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。


  • 插件进程。主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。


相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
JavaScript 前端开发
牛客刷题Day3(三)
牛客刷题Day3(三)
92 0
|
前端开发
牛客刷题Day3
牛客刷题Day3
94 0
牛客刷题
牛客刷题
86 0
牛客刷题(buhui/(ㄒoㄒ)/~~)
牛客刷题(buhui/(ㄒoㄒ)/~~)
牛客刷题(buhui/(ㄒoㄒ)/~~)
|
资源调度 算法 网络协议
牛客面经每日一总结 (八)
牛客面经每日一总结 (八)
|
前端开发 算法 JavaScript
牛客面经每日一总结(四)
牛客面经每日一总结(四)
|
存储 消息中间件 设计模式
牛客面经每日一总结(五)
牛客面经每日一总结(五)
|
消息中间件 存储 Web App开发
牛客面经每日一总结(二)
牛客面经每日一总结(二)
|
存储 缓存 前端开发
牛客面经每日一总结(三)
牛客面经每日一总结(三)
|
存储 移动开发 JSON
牛客面经每日一总结(六)
牛客面经每日一总结(六)