- TCP 建立连接的三次握手过程
参考答案:
第一次握手:起初两端都处于 CLOSED 关闭状态,Client 将标志位 SYN 置为 1, 随机产生一个值 seq=x,并将该数据包发送给 Server,Client 进入 SYN-SENT 状态,等待 Server 确认;
第二次握手:Server 收到数据包后由标志位 SYN=1 得知 Client 请求建立连接, Server 将标志位 SYN 和 ACK 都置为 1,ack=x+1,随机产生一个值 seq=y,并将该数据包发送给 Client 以确认连接请求,Server 进入 SYN-RCVD 状态,此时操作系统为该 TCP 连接分配 TCP 缓存和变量;
第三次握手:Client 收到确认后,检查 ack 是否为 x+1,ACK 是否为 1,如果正确则将标志位 ACK 置为 1,ack=y+1,并且此时操作系统为该 TCP 连接分配 TCP 缓存和变量,并将该数据包发送给 Server,Server 检查 ack 是否为 y+1,ACK
是否为 1,如果正确则连接建立成功,Client 和 Server 进入 ESTABLISHED 状态, 完成三次握手,随后 Client 和 Server 就可以开始传输数据。
- cdn 原理
参考答案:
CDN 的全称是 Content Delivery Network,即内容分发网络。CDN 的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响
HTTP 的头部包含哪些内容。常见的请求方法(我为什么要说后面的 options,head,connect)
参考答案:常见的请求方法有 get,post,get 用来请求数据,post 用来提交数据,form 表单使用 get 时数据会以 querystring 形式存在 url 中,因而不够安全也存在数据大小限制,而 post 不会,post 将数据存放在 http 报文体中,获取数据应该用get,提交数据用 post
- 请求方法 head 特性
参考答案:
Head 只请求页面的首部,head 方法和 get 方法相同,只不过服务器响应时不会返回消息体,一个 head 请求的响应中,http 头中包含的元信息应该和一个 get 请求的响应消息相同,这种方法可以用来获取请求中隐含的元信息,而不用传输实体本身,这个也经常用来测试超链接的有效性和可用性,
Head 请求有以下特点: 只请求资源的首部, 检查超链接的有效性 检查网页是否被修改
用于自动搜索机器人获取网页的标志信息,获取 rss 种子信息,或者传递安全认证信息等
HTTP 状态码,301 和 302 有什么具体区别,200 和 304 的区别
参考答案:
状态码可以按照第一个数字分类
1 表示信息,2 表示成功,3 表示重定向,4 表示客户端错误,5 表示服务器错误常见的状态码有:
101 切换协议,200 成功,301 永久重定向,302 临时重定向,304 未修改
301 和 302 的区别:
301:永久移动,请求的网页已永久移动到新的位置,服务器返回此响应,会自动将请求者转到新位置;
302:历史移动,服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来继续以后的请求;200 和 304:
200 表示成功,服务器已成功处理了请求,通常表示为服务器提供了请求的网页;
304 表示未修改,自从上次请求后,请求的网页未修改过,服务器返回此响应时不会返回网页内容;
- OSI 七层模型
参考答案:
osi 七层模型可以说是面试必考基础了
从上到下分别是:
应用层:文件传输,常用协议 HTTP,snmp,FTP , 表示层:数据格式化,代码转换,数据加密, 会话层:建立,解除会话
传输层:提供端对端的接口,tcp,udp 网络层:为数据包选择路由,IP,icmp 数据链路层:传输有地址的帧
物理层:二进制的数据形式在物理媒体上传输数据
- TCP 和 UDP 的区别,为什么三次握手四次挥手
参考答案:
TCP 和 UDP 之间的区别:
OSI 和 TCP/IP 模型在传输层定义两种传输协议:TCP(或传输控制协议)和 UDP
(或用户数据报协议)。 UDP 与 TCP 的主要区别在于 UDP 不一定提供可靠的数据传输。 事实上,该协议不能保证数据准确无误地到达目的地。
为什么 TCP 要进行四次挥手呢?
因为是双方彼此都建立了连接,因此双方都要释放自己的连接,A 向 B 发出一个释放连接请求,他要释放链接表明不再向 B 发送数据了,此时 B 收到了 A 发送的释放链接请求之后,给 A 发送一个确认,A 不能再向 B 发送数据了,它处于FIN-WAIT-2 的状态,但是此时 B 还可以向 A 进行数据的传送。此时 B 向 A 发送一个断开连接的请求,A 收到之后给 B 发送一个确认。此时 B 关闭连接。A 也关闭连接。
为什么要有 TIME-WAIT 这个状态呢,
这是因为有可能最后一次确认丢失,如果 B 此时继续向 A 发送一个我要断开连接的请求等待 A 发送确认,但此时 A 已经关闭连接了,那么 B 永远也关不掉了,所以我们要有 TIME-WAIT 这个状态。
当然 TCP 也并不是 100%可靠的。
- HTTP 缓存机制
参考答案:
HTTP 缓存即是浏览器第一次想一个服务器发起 HTTP 请求后,服务器会返回请求的资源, 并且在响应头中添加一些有关缓存的字段如: cache-control, expires,last-modifed,ETag,Date,等,之后浏览器再向该服务器请求资源就可以视情况使用强缓存和协商缓存,
强缓存:浏览器直接从本地缓存中获取数据,不与服务器进行交互, 协商缓存:浏览器发送请求到服务器,服务器判断是否可使用本地缓存
websocket 和 ajax 的区别是什么,websocket 的应用场景有哪些
参考答案:WebSocket 的诞生本质上就是为了解决 HTTP 协议本身的单向性问题:请求必须由客户端向服务端发起,然后服务端进行响应。这个 Request-Response 的关系是无法改变的。对于一般的网页浏览和访问当然没问题,一旦我们需要服务端主动向客户端发送消息时就麻烦了,因为此前的 TCP 连接已经释放,根本找不到客户端在哪。
为了能及时从服务器获取数据,程序员们煞费苦心研究出来的各种解决方案其实都是在 HTTP 框架下做的妥协,没法子,浏览器这东西只支持 HTTP,我们有什么办法。所以大家要么定时去轮询,要么就靠长连接——客户端发起请求,服务端把这个连接攥在手里不回复,等有消息了再回,如果超时了客户端就再请求一次
——其实大家也懂,这只是个减少了请求次数、实时性更好的轮询,本质没变。WebSocket 就是从技术根本上解决这个问题的:看名字就知道,它借用了 Web 的端口和消息头来创建连接,后续的数据传输又和基于 TCP 的 Socket 几乎完全一样,但封装了好多原本在 Socket 开发时需要我们手动去做的功能。比如原生支持 wss 安全访问(跟 https 共用端口和证书)、创建连接时的校验、从数据帧中自动拆分消息包等等。换句话说,原本我们在浏览器里只能使用 HTTP 协议,现在有了 Socket,还是个更好用的 Socket。
了解了 WebSocket 的背景和特性之后,就可以回答它能不能取代 AJAX 这个问题了:
对于服务器与客户端的双向通信,WebSocket 简直是不二之选。如果不是还有少数旧版浏览器尚在服役的话,所有的轮询、长连接等方式早就该废弃掉。那些整合多种双向推送消息方式的库(如 http://Socket.IO、SignalR)当初最大的卖点就是兼容所有浏览器版本,自动识别旧版浏览器并采取不同的连接方式,现在也渐渐失去了优势——所有新版浏览器都兼容 WebSocket,直接用原生的就行了。说句题外话,这点很像 jQuery,在原生 js 难用时迅速崛起,当其他库和原生 js 都吸收了它的很多优势时,慢慢就不那么重要了。
但是,很大一部分 AJAX 的使用场景仍然是传统的请求-响应形式,比如获取 json 数据、post 表单之类。这些功能虽然靠 WebSocket 也能实现,但就像在原本传输数据流的 TCP 之上定义了基于请求的 HTTP 协议一样,我们也要在 WebSocket 之上重新定义一种新的协议,最少也要加个 request id 用来区分每次响应数据
对应的请求吧。
……但是,何苦一层叠一层地造个新轮子呢?直接使用 AJAX 不是更简单、更成熟吗?
另外还有一种情况,也就是传输大文件、图片、媒体流的时候,最好还是老老实实用 HTTP 来传。如果一定要用 WebSocket 的话,至少也专门为这些数据专门开辟个新通道,而别去占用那条用于推送消息、对实时性要求很强的连接。否则会把串行的 WebSocket 彻底堵死的。
所以说,WebSocket 在用于双向传输、推送消息方面能够做到灵活、简便、高效, 但在普通的 Request-Response 过程中并没有太大用武之地,比起普通的 HTTP 请求来反倒麻烦了许多,甚至更为低效。
每项技术都有自身的优缺点,在适合它的地方能发挥出最大长处,而看到它的几个优点就不分场合地全方位推广的话,可能会适得其反。
我们自己在开发能与手机通信的互联网机器人时就使用了 WebSocket,效果很好。但并不是用它取代 HTTP,而是取代了原先用于通信的基于 TCP 的 Socket。
优点是:
原先在 Socket 连接后还要进行一些复杂的身份验证,同时要阻止未验证的连接发送控制指令。现在不需要了,在建立 WebSocket 连接的 url 里就能携带身份验证参数,验证不通过可以直接拒绝,不用设置状态;
原先自己实现了一套类似 SSL 的非对称加密机制,现在完全不需要了,直接通过wss 加密,还能顺便保证证书的
可信性;
原先要自己定义 Socket 数据格式,设置长度与标志,处理粘包、分包等问题, 现在 WebSocket 收到的直接就是完整的数据包,完全不用自己处理;
前端的 nginx 可以直接进行转发与负载均衡,部署简单多了
- TCP/IP 的网络模型
参考答案:
TCP/IP 模型是一系列网络协议的总称,这些协议的目的是使得计算机之间可以进行信息交换,
TCP/IP 模型四层架构从下到上分别是链路层,网络层,传输层,应用层
链路层的作用是负责建立电路连接,是整个网络的物理基础,典型的协议包括以太网,ADSL 等,
网络层负责分配地址和传送二进制数据,主要协议是 IP 协议, 传输层负责传送文本数据,主要协议是 TCP
应用层负责传送各种最终形态的数据,是直接与用户信息打交道的层,主要协议是 http,ftp 等
知道什么跨域方式吗,jsonp 具体流程是什么,如何实现原生 Jsonp 封装,优化,对于 CORS,服务器怎么判断它该不该跨域呢
参考答案:常见的跨域方式大概有七种,大致可分为 iframe、api 跨域
1) JSONP,全称为 json with padding,解决老版本浏览器跨域数据访问问题, 原理是 web 页面调用 JS 文件不受浏览器同源策略限制,所以通过 script 标签可以进行跨域请求,流程如下:
首先前端设置好回调参数,并将其作为 URL 的参数
服务器端收到请求后,通过该参数获取到回调函数名,并将数据放在参数中返回收到结果后因为是 script 标签,所以浏览器当做脚本运行,2) cors,全称是跨域资源共享,允许浏览器向跨源服务器发出 XMLHTTP Request请求,从而克服了 ajax 只能同源使用的策略,实现 cors 的关键是服务器,只要服务器实现了 cros 接口,就可以跨域通信
前端逻辑很简单, 正常发起 ajax 请求即可, 成功的关键在于服务器Access-Control-Allow-Origin 是否包含请求页面的域名,如果不包含的话,浏览器将认为这是一次失败的异步请求,将会调用 xhr.onerror 中的函数。Cros 使用简单,支持 POST 方式,但是存在兼容问题
浏览器将 cors 请求分为两类,简单请求和非简单请求,对于简单请求,浏览器直接发出 cors 请求,就是在头信息之中增加一个 origin 字段,用于说明本次请求来自哪个协议+域名+端口,服务器根据这个值,决定是否同意本次请求,如果服务器同意本次请求,返回的响应中会多出几个头信息字段:
Access-Control-Allow-Orign:返回 origin 的字段或者*
Access-Control-Allow-Credentials,该字段可选,是一个 bool 值,表示是否允许发送 cookie,
Access-Control-Expose-Headers3) 服务器代理:
即当你有跨域的请求操作时发给后端,让后端帮你代为请求, 此外还有四中不常用的方式,也可了解下:
location.hash: Window.name postMessage
- 怎么生成 token,怎么传递
参考答案:
接口特点汇总:
1) 因为是非开放性的,所以所有的接口都是封闭的,只对公司内部的产品有效;
2) 因为是非开放性的,所以 OAuth 那套协议是行不通的,因为没有中间用户的授权过程;
3) 有点接口需要用户登录才能访问;
4) 有点接口不需要用户登录就可访问;
针对以上特点,移动端与服务端的通信就需要 2 把钥匙,即 2 个 token。第一个 token 是针对接口的(api_token);
第二个 token 是针对用户的(user_token); 先说第一个 token(api_token)
它的职责是保持接口访问的隐蔽性和有效性,保证接口只能给自家人用,怎么做到?参考思路如下:
现在的接口基本是 mvc 模式,URL 基本是 restful 风格,URL 大体格式如下: http://blog.snsgou.com/模块名/控制器名/方法名?参数名 1=参数值 1&参数名2=参数值 2&参数名 3=参数值 3
接口 token 生成规则参考如下:
api_token = md5 ('模块名' + '控制器名' + '方法名' + '2017-07-18' + ' 加密密钥') =770fed4ca2aabd20ae9a5dd774711de2其中的
1) '2013-12-18' 为当天时间,
2)'加密密钥' 为私有的加密密钥,手机端需要在服务端注册一个“接口使用者” 账号后,系统会分配一个账号及密码,数据表设计参考如下:服务端接口校验,PHP 实现流程如下:
<?php
1) 获取 GET 参数值 $module = $_GET['mod']; $controller = $_GET['ctl']; $action = $_GET['act']; $client_id = $_GET['client_id']; $api_token = $_GET['api_token']; 2) 根据客户端传过来的 client_id,查询数据库,获取对应的 client_secret。 $client_secret = getclientSecretById($client_id); 3) 服务器重新生成一份 api_token $api_token_server = md5($module.$controller.$action.date('Y-m-d', time()).$client_secret); 4) 客户端传过来的 api_token 与服务器生成的 api_token 进行校对,如果不相等,则表示验证失败。 if($api_token != $api_token_server){ exit('access deny'); } 5) 验证通过,返回数据到客户端。 再说第二个 token(user_token),它的职责是保护用户的用户名及密码多次提交,以防密码泄露。 如果接口需要用户登录,其访问流程如下: 1) 用户提交“用户名”和“密码”,实现登录(条件允许,这一步最好走 https); 2) 登录成功后,服务端返回一个 user_token,生成规则参考如下:
服务端用数据表维护 user_token 的状态,表设计如下:
服务端生成 user_token 后,返回给客户端(自己存储),客户端每次接口请求时,如果接口需要用户登录才能访问,则需要把 user_id 与 user_token 传回给服务端,服务端接受到这 2 个参数后,需要做以下几步:
1) 检测 api_token 的有效性; 2) 删除过期的 user_token 表记录; 3) 根据 user_id,user_token 获取表记录,如果表记录不存在,直接返回错误,如果记录存在,则进行下一步; 4) 更新 user_token 的过期时间(延期,保证其有效期内连续操作不掉线); 5) 返回接口数据。
那么 token 如何传递呢,ajax 中传递 token 有以下几种方式:
(1) 放在请求头中:
(2) 使用 beforeSend 方法设置请求头
- 操作系统进程和线程的区别
参考答案:
进程,是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。
线程,是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,也是 CPU 调度的一个基本单位。
- 什么是进程 线程
参考答案:
进程,是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。
线程,是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,也是 CPU 调度的一个基本单位。
- 线程的那些资源共享,那些资源不共享
参考答案:
共享的资源有
a. 堆由于堆是在进程空间中开辟出来的,所以它是理所当然地被共享的;因此new 出来的都是共享的(16 位平台上分全局堆和局部堆,局部堆是独享的)
b. 全局变量 它是与具体某一函数无关的,所以也与特定线程无关;因此也是共享的
c. 静态变量虽然对于局部变量来说,它在代码中是“放”在某一函数中的,但是其存放位置和全局变量一样,存于堆中开辟的.bss 和.data 段,是共享的
d. 文件等公用资源 这个是共享的,使用这些公共资源的线程必须同步。Win32 提供了几种同步资源的方式,包括信号、临界区、事件和互斥体。独享的资源有:
a. 栈 栈是独享的
b. 寄存器 这个可能会误解,因为电脑的寄存器是物理的,每个线程去取值难道不一样吗?其实线程里存放的是副本,包括程序计数器 PC
- 操作系统里面进程和线程的区别
参考答案:
进程是具有一定独立功能的程序,他是系统进行资源分配调度的一个独立单位, 线程是进程的一个实体,是 cpu 调度分派的基本单位,线程之间基本上不拥有系统资源
一个程序至少有一个进程,一个进程至少有一个线程,资源分配给进程,同一个进程下所有线程共享该进程的资源
- Linux 查询进程指令,查询端口,杀进程
参考答案:
查询进程: ps 命令用于查看当前正在运行的进程。grep 是搜索 例如: ps -ef | grep java 表示查看所有进程里 CMD 是 java 的进程信息ps -aux | grep java -aux 显示所有状态ps 杀死进程: kill -9[PID]
- 进程间的通信式有哪些?
参考答案:
总共有八种,面试中只要能大概答上三四种方式的原理就可以了
(1) 无名管道:半双工的通信方式,数据只能单向流动且只能在具有亲缘关系的进程间使用
(2) 高级管道:将另一个程序当作一个新的进程在当前程序进程中启动,则这个进程算是当前程序的子进程,
(3) 有名管道,:也是半双工的通信方式,但是允许没有亲缘进程之间的通信
(4) 消息队列:消息队列是有消息的链表,存放在内核中,并由消息队列标识符标识,消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限的缺点
(5) 信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问, 它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源,
(6) 信号:用于通知接受进程某个事件已经发生
(7) 共享内存:共享内存就是映射一段能被其他进程所访问的内存。这段共享内存由一个进程创建,但是多个进程可以访问,共享内存是最快的 IPC 方式, 往往与其他通信机制配合使用
(8) 套接字:可用于不同机器之间的进程通信
- Redis 和 mysql
参考答案:
(1) 类型上
从类型上来说,mysql 是关系型数据库,redis 是缓存数据库
(2) 作用上
mysql 用于持久化的存储数据到硬盘,功能强大,但是速度较慢redis 用于存储使用较为频繁的数据到缓存中,读取速度快
(3) 需求上
mysql 和 redis 因为需求的不同,一般都是配合使用。
全部评论
(2) 回帖