计算机网络

锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制。锁旨在强制实施互斥排他、并发控制策略。

常见锁机制

读写锁、可重入锁、乐观锁、悲观锁、公平锁、非公平锁

死锁

Java中的死锁是一种编程情况,其中两个或多个线程被永久阻塞,Java死锁情况出现至少两个线程和两个或更多资源。
Java发生死锁的根本原因是:在申请锁时发生了交叉闭环申请。

  • 是多个线程涉及到多个锁,这些锁存在着交叉,所以可能会导致了一个锁依赖的闭环。
    例如:线程在获得了锁A并且没有释放的情况下去申请锁B,这时,另一个线程已经获得了锁B,在释放锁B之前又要先获得锁A,因此闭环发生,陷入死锁循环。
  • 默认的锁申请操作是阻塞的。
    所以要避免死锁,就要在一遇到多个对象锁交叉的情况,就要仔细审查这几个对象的类中的所有方法,是否存在着导致锁依赖的环路的可能性。总之是尽量避免在一个同步方法中调用其它对象的延时方法和同步方法。

独享锁/共享锁

独享锁是指该锁一次只能被一个线程所持有。 (ReentrantLock、 Synchronized)
共享锁是指该锁可被多个线程所持有。 (ReadWriteLock)
互斥锁/读写锁
独享锁/共享锁这是广义上的说法,互斥锁/读写锁就分别对应具体的实现。在Java中如ReentrantLock就是互斥锁(独享锁), ReadWriteLock就是读写锁(共享锁)。 独享锁与共享锁也是通过AQS来实现的
锁升级:读锁到写锁 (不支持)
锁降级:写锁到读锁 (支持)

公平锁 & 非公平锁

公平锁是指多个线程按照申请锁的顺序来获取锁。
非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能会造成饥饿现象。
对于Java ReentrantLock而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。
对于Synchronized而言,也是一种非公平锁。由于其并不像ReentrantLock是通过AQS的控制线程对锁的获取, 所以并没有任何办法使其变成公平锁。

乐观锁 & 悲观锁

乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。
悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十一,直接上了锁就操作资源了。

实现读写锁ReentrantReadWriteLock

低16位代表写锁,高16位代表读锁

可重入锁ReetrantLock原理

可重入锁又名递归锁,是指同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。
ReentrantLock和Synchronized都是可重入锁。可重入锁的一个好处是可一定程度避免死锁。
ReentrantLock主要利用CAS+AQS队列来实现。它支持公平锁和非公平锁,两者的实现类似。
CAS:Compare and Swap,比较并交换。CAS有3个操作数:内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。该操作是一个原子操作,被广泛的应用在Java的底层实现中。在Java中,CAS主要是由sun.misc.Unsafe这个类通过JNI调用CPU底层指令实现
AbstractQueuedSynchronizer简称AQS,是一个用于构建锁和同步容器的框架。事实上concurrent包内许多类都是基于AQS构建,例如ReentrantLock,Semaphore,CountDownLatch,ReentrantReadWriteLock,FutureTask等。AQS解决了在实现同步容器时设计的大量细节问题。

synchronized和ReentrantLock的区别

synchronized是和if、else、for、while一样的关键字,ReentrantLock是类,这是二者的本质区别。既然ReentrantLock是类,那么它就提供了比synchronized更多更灵活的特性,可以被继承、可以有方法、可以有各种各样的类变量,ReentrantLock比synchronized的扩展性体现在几点上:

  • ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁
  • ReentrantLock可以获取各种锁的信息
  • ReentrantLock可以灵活地实现多路通知

如果有多个变量要更新,要保证一致性,怎样加锁来保证正确性,效率又比较高?

只在写时加锁,读不加锁

那怎么解决一个写操作修改了部分变量,读操作,读取了这个中间状态的问题?

写操作时,先锁住锁1,在线程本地也就是函数局部计算完所有结果后,锁住锁2,一次更新完后再释放2个锁,读操作只锁住锁2

synchronized & lock

synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。

https://blog.csdn.net/tanmomo/article/details/99671622
https://blog.csdn.net/fuyuwei2015/article/details/83719444
https://zhuanlan.zhihu.com/p/108224026?from_voters_page=true
https://blog.csdn.net/natian306/article/details/18504111

TCP & UDP

TCP和UDP有什么区别?

  1. TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
  2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
  3. TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的。UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
  4. 每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
  5. TCP首部开销20字节;UDP的首部开销小,只有8个字节
  6. TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

具体编程时的区别

  1. socket()的参数不同
  2. UDP Server不需要调用listen和accept
  3. UDP收发数据用sendto/recvfrom函数
  4. TCP:地址信息在connect/accept时确定
  5. UDP:在sendto/recvfrom函数中每次均 需指定地址信息
  6. UDP:shutdown函数无效

TCP可靠性机制

检验和

TCP检验和的计算与UDP一样,在计算时要加上12byte的伪首部,检验范围包括TCP首部及数据部分,但是UDP的检验和字段为可选的,而TCP中是必须有的。计算方法为:在发送方将整个报文段分为多个16位的段,然后将所有段进行反码相加,将结果存放在检验和字段中,接收方用相同的方法进行计算,如最终结果为检验字段所有位是全1则正确(UDP中为0是正确),否则存在错误。

序列号

TCP将每个字节的数据都进行了编号,这就是序列号。
序列号的作用:
a. 保证可靠性(当接收到的数据总少了某个序号的数据时,能马上知道)
b. 保证数据的按序到达
c. 提高效率,可实现多次发送,一次确认
d. 去除重复数据
数据传输过程中的确认应答处理、重发控制以及重复控制等功能都可以通过序列号来实现

确认应答机制(ACK)

TCP通过确认应答机制实现可靠的数据传输。在TCP的首部中有一个标志位——ACK,此标志位表示确认号是否有效。接收方对于按序到达的数据会进行确认,当标志位ACK=1时确认首部的确认字段有效。进行确认时,确认字段值表示这个值之前的数据都已经按序到达了。而发送方如果收到了已发送的数据的确认报文,则继续传输下一部分数据;而如果等待了一定时间还没有收到确认报文就会启动重传机制。

超时重传机制

当报文发出后在一定的时间内未收到接收方的确认,发送方就会进行重传(通常是在发出报文段后设定一个闹钟,到点了还没有收到应答则进行重传)
当接收方接收到重复的数据时就将其丢掉,重新发送ACK。而要识别出重复的数据,就要用到前面提到的序列号了,利用序列号很容易就可以做到去重的效果。

连接管理机制

连接管理机制即TCP建立连接时的三次握手和断开连接时的四次挥手。

三次握手:

  • 客户端发出:syn包(seq=j),并进入SYN_SENT状态,等待服务器确认。
  • 服务端发出:ack=j+1,同时自己也发送一个SYN包(seq=k),此时服务器进入SYN_RECV状态。
  • 客户端发出:确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

四次挥手:

  • 主机1发出:主机1(可以使客户端,也可以是服务器端),设置序列号Seq和确认号ACK,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
  • 主机2发出:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,ACK = Seq + 1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;
  • 主机2发出:FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;
  • 主机1发出:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

FIN_WAIT_1: 其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。(主动方)
FIN_WAIT_2:实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你(ACK信息),稍后再关闭连接。(主动方)
CLOSE_WAIT:表示在等待关闭。当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。(被动方)
LAST_ACK: 被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。(被动方)
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN WAIT1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。(主动方)
CLOSED: 表示连接中断。

停止等待协议

停止等待协议是一种ARQ协议。(Automatic Repeat reQuest自动重传请求)
A向B每发送一个分组,都要停止发送,等待B的确认应答;A只有收到了B的确认应答后才能发送下一个分组。当分组丢失或出现差错 的情况下,A都会超时重传分组。TCP会给每个字节都打上序号,用于判断该分组是否已经接收。

  • 必须设置超时计时器。每发送一个分组就要启动计时器,超时就要重发分组。计时器的超时时间要大于应答的平均返回时间,否则会出现很多不必要的重传,降低传输效率。但超时时间也不能太长。

流量控制 滑动窗口(发送窗口和接收窗口)

在ARQ协议发送者每次只能发送一个分组,在应答到来前必须等待。而连续ARQ协议的发送者拥有一个发送窗口,发送者可以在没有得到应答的情况下连续发送窗口中的分组。这样降低了等待时间,提高了传输效率。
接收端处理数据的速度是有限的,如果发送方发送数据的速度过快,导致接收端的缓冲区满,而发送方继续发送,就会造成丢包,继而引起丢包重传等一系列连锁反应。
TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制叫做流量控制。
在TCP报文段首部中有一个16位窗口长度,当接收端接收到发送方的数据后,在应答报文ACK中就将自身缓冲区的剩余大小,放入16窗口大小中。这个大小随数据传输情况而变,窗口越大,网络吞吐量越高,而一旦接收方发现自身的缓冲区快满了,就将窗口设置为更小的值通知发送方。如果缓冲区满,就将窗口置为0,发送方收到后就不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。

  • 已经发送并且对端确认(Sent/ACKed)———————-发送窗外 缓冲区外
    已经发送但未收到确认数据(Sent/UnACKed) ————-发送窗内 缓冲区内
    允许发送但尚未防的数据(Unsent/Inside)—————发送窗内 缓冲区内
    未发送暂不允许(Unsent/Outside)————————-发送窗外 缓冲区内
    第二、三为发送窗口,存放在TCP header中有一个Window Size字段,用来告知发送端自己所能接收的数据量,从而达到一部分流控的目的。
  • 对于TCP的接收方,在某一时刻在它的接收缓存内存在3种。
    “已接收”,“未接收准备接收”,“未接收并未准备接收”(由于ACK直接由TCP协议栈回复,默认无应用延迟,不存在“已接收未回复ACK”)。
    其中“未接收准备接收”称之为接收窗口。
  • TCP是双工的协议,会话的双方都可以同时接收、发送数据。TCP会话的双方都各自维护一个“发送窗口”和一个“接收窗口”。其中各自的“接收窗口”大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。各自的“发送窗口”则要求取决于对端通告的“接收窗口”,要求相同。

拥塞控制

流量控制解决了两台主机之间因传送速率而可能引起的丢包问题,在一方面保证了TCP数据传送的可靠性。然而如果网络非常拥堵,此时再发送数据就会加重网络负担,那么发送的数据段很可能超过了最大生存时间也没有到达接收方,就会产生丢包问题。
为此TCP引入慢启动机制,先发出少量数据,就像探路一样,先摸清当前的网络拥堵状态后,再决定按照多大的速度传送数据。
此处引入一个拥塞窗口
发送开始时定义拥塞窗口大小为1;每次收到一个ACK应答,拥塞窗口加1;而在每次发送数据时,发送窗口取拥塞窗口与接送段接收窗口最小者。
慢启动:在启动初期以指数增长方式增长;设置一个慢启动的阈值,当以指数增长达到阈值时就停止指数增长,按照线性增长方式增加;线性增长达到网络拥塞时立即“乘法减小”,拥塞窗口置回1,进行新一轮的“慢启动”,同时新一轮的阈值变为原来的一半。

TCP长连接 & 短连接

  • 长连接,也叫持久连接,在TCP层握手成功后,不立即断开连接,并在此连接的基础上进行多次消息(包括心跳)交互,直至连接的任意一方(客户端OR服务端)主动断开连接,此过程称为一次完整的长连接。HTTP 1.1相对于1.0最重要的新特性就是引入了长连接。
    短连接

  • 短连接,客户端收到服务端的响应后,立刻发送FIN消息,主动释放连接。也有服务端主动断连的情况,凡是在一次消息交互(发请求-收响应)之后立刻断开连接的情况都称为短连接。短连接是建立在TCP协议上的,有完整的握手挥手流程,区别于UDP协议。

UDP有拥塞控制吗?如何解决?

UDP没有拥塞控制,可以根据丢包率来判断网络的拥塞情况,如果网络拥塞,接收方通知发送方调整发送速率从而有效解决公平性问题以及UDP的拥塞控制问题。

为什么要有 time_wait

假设最终的ACK丢失,主机2将重发FIN,主机1必须维护TCP状态信息以便可以重发最终的ACK,否则会发送RST,结果主机2认为发生错误。TCP实现必须可靠地终止连接的两个方向(全双工关闭),主机1必须进入 TIME_WAIT 状态,因为主机1可能面临重发最终ACK的情形。

https://www.zhihu.com/question/47378601/answer/276353285
https://blog.csdn.net/xuzhangze/article/details/80490362
https://www.cnblogs.com/xdyixia/p/9294885.html
https://www.cnblogs.com/hongdada/p/11171068.html
https://www.cnblogs.com/Paul-watermelon/p/11141422.html
https://xueshu.baidu.com/usercenter/paper/show?paperid=6576ba05a97ec447bcf1111cbd0485e9&site=xueshu_se
https://blog.51cto.com/11859650/1917938

http & https

http与https的区别

HTTPS是在HTTP上建立SSL加密层,并对传输数据进行加密,是HTTP协议的安全版。HTTPS协议,它比HTTP协议相比多了以下优势:
数据隐私性:内容经过对称加密,每个连接生成一个唯一的加密密钥
数据完整性:内容传输经过完整性校验
身份认证:第三方无法伪造服务端(客户端)身份(数字签名)
发送密文的一方使用对方的公钥进行加密处理“对称的密钥”,然后对方用自己的私钥解密拿到“对称的密钥”,这样可以确保交换的密钥是安全的前提下,使用对称加密方式进行通信。所以,HTTPS采用对称加密和非对称加密两者并用的混合加密机制。

  • HTTPS比HTTP更加安全,对搜索引擎更友好,利于SEO,谷歌、百度优先索引HTTPS网页;
  • HTTPS需要用到SSL证书,而HTTP不用;
  • HTTPS标准端口443,HTTP标准端口80;
  • HTTPS基于传输层,HTTP基于应用层;
  • HTTPS在浏览器显示绿色安全锁,HTTP没有显示;s
  • HTTPS需要使用证书,必须向认证机构(CA)购买。
  • HTTPS加密通信会消耗更多的CPU及内存资源

浏览器中输入网址到获得页面的全过程

  1. 浏览器中输入域名www.baidu.com
  2. 域名解析DNS得到对应的ip
    找浏览器缓存->查看本机的host文件->路由器缓存->对本地DNS服务器进行递归查询->本地域名服务器采用迭代查询->根域名服务器(告诉本地顶级ip)->顶级域名服务器(告诉本地权威ip)->权威域名服务器(告诉本地查找结果)->本地域名服务器把查询结果告诉本机。
  3. 浏览器与目标服务器建立TCP连接:3次握手连接
  4. 浏览器通过http协议向目标服务器发送请求
    浏览器向主机发起一个HTTP-GET方法报文请求。请求中包含访问的URL,也就是http://www.baidu.com/等信息。Cookies如果是首次访问,会提示服务器建立用户缓存信息。
  5. 服务器给出响应,将指定文件发送给浏览器
    状态行,响应头,响应实体内容,返回状态码200 OK,表示服务器可以响应请求,返回报文,由于在报头中Content-type为“text/html”,浏览器以HTML形式呈现,而不是下载文件。
  6. TCP释放链接
    浏览器所在主机向服务器发出连接释放报文,然后停止发送数据;
    服务器接收到释放报文后发出确认报文,然后将服务器上未传送完的数据发送完;
    服务器数据传输完毕后,向客户机发送连接释放报文;
    客户机接收到报文后,发出确认,然后等待一段时间后,释放TCP连接;
  7. 浏览器显示页面中所有文本。
    浏览器接收到返回的数据包,根据浏览器的渲染机制对相应的数据进行渲染。渲染后的数据,进行相应的页面呈现和脚步的交互。
  • 涉及到的协议
    应用层:HTTP(WWW访问协议),DNS(域名解析服务)
    传输层:TCP(为HTTP提供可靠的数据传输),UDP(DNS使用UDP传输)
    网络层:IP(IP数据数据包传输和路由选择),ICMP(提供网络传输过程中的差错检测),ARP(将本机的默认网关IP地址映射成物理MAC地址)

输入 www.baidu.com,怎么变成 https://www.baidu.com 的,怎么确定用HTTP还是HTTPS?

一种是原始的302跳转,服务器把所有的HTTP流量跳转到HTTPS。但这样有一个漏洞,就是中间人可能在第一次访问站点的时候就劫持。
解决方法是引入HSTS机制,用户浏览器在访问站点的时候强制使用HTTPS。

HTTP可以使用UDP吗

HTTP3。对传输的报文进行充分的加密

HTTP协议的报文格式

客户端请求request报文格式:请求行(请求方法,URL,HTTP协议版本)、请求头部(header)、空行、请求数据
服务器响应response报文格式:状态行(HTTP协议版本, 状态码, 状态消息)、消息报头、空行、响应正文

Http1.0 & HTTP1.1

  1. 缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  2. 带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  3. 错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
  4. Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
  5. 长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

HTTP2.0和HTTP1.X相比的新特性

  1. 新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
  2. 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
  3. header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
  4. 服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。

HTTP请求方法

  1. GET方法意思是获取URL指定的资源,使用GET方法时,可以将请求参数和对应的值附加在 URI 后面,利用一个问号(“?”)将资源的URI和请求参数隔开,参数之间使用与符号(“&”)隔开,因此传递参数长度也受到了限制,而且与隐私相关的信息也直接暴露在URI中。比如/index.jsp?username=holmofy&password=123123
  2. HEAD 方法与GET用法相同,但没有响应体,使用场合没有GET多。比如下载前使用HEAD发送请求,通过ContentLength响应字段,来了解网络资源的大小;或者通过LastModified响应字段来判断本地缓存资源是否要更新。
  3. POST 方法一般用提交信息或数据,请求服务器进行处理(例如提交表单或者上传文件)。表单使用POST相对GET来说还是比较隐秘的,而且GET的URL有长度限制,而上传大文件就必须要使用POST了。
  4. OPTIONS方法比较少见,该方法用于请求服务器告知其支持哪些其他的功能和方法。通过OPTIONS 方法,可以询问服务器具体支持哪些方法,或者服务器会使用什么样的方法来处理一些特殊资源。可以说这是一个探测性的方法,客户端通过该方法可以在不访问服务器上实际资源的情况下就知道处理该资源的最优方式。这个选项在跨域HTTP请求的情况出现的比较多,这里有一片关于跨域请求的文章,其中有一张图很好的解释了什么是跨域HTTP请求。

GET与POST的区别

GET是幂等的,即读取同一个资源,总是得到相同的数据,POST不是幂等的;
GET一般用于从服务器获取资源,而POST有可能改变服务器上的资源;
请求形式上:GET请求的数据附在URL之后,在HTTP请求头中;POST请求的数据在请求体中;
安全性:GET请求可被缓存、收藏、保留到历史记录,且其请求数据明文出现在URL中。POST的参数不会被保存,安全性相对较高;
GET只允许ASCII字符,POST对数据类型没有要求,也允许二进制数据;
GET的长度有限制(操作系统或者浏览器),而POST数据大小无限制

常见的状态码

1XX:信息提示。表示请求已被服务器接受,但需要继续处理,范围为100~101。
2XX:请求成功。服务器成功处理了请求。范围为200~206。
3XX:客户端重定向。重定向状态码用于告诉客户端浏览器,它们访问的资源已被移动,并告诉客户端新的资源位置。客户端收到重定向会重新对新资源发起请求。范围为300~305。
4XX:客户端信息错误。客户端可能发送了服务器无法处理的东西,比如请求的格式错误,或者请求了一个不存在的资源。范围为400~415。
5XX:服务器出错。客户端发送了有效的请求,但是服务器自身出现错误,比如Web程序运行出错。范围是500~505。
200: ok
304: not modified
400: bad request
404: not found

https://blog.csdn.net/Goligory/article/details/104513317
https://blog.csdn.net/qiuchaoxi/article/details/79415400
https://www.cnblogs.com/jpfss/p/10984966.html
https://blog.csdn.net/qq_38128179/article/details/85068195
https://blog.csdn.net/qq_40638598/article/details/105293250
https://www.cnblogs.com/heluan/p/8620312.html

Cookie & Session

Cookie的参数有哪些?

setcookie()函数向客户端发送一个 HTTP cookie。
cookie的名称指定为相同名称的变量。例如,如果被发送的 cookie 名为 “name”,会自动创建名为 $user 的变量,包含cookie 的值。
setcookie(name,value,expire,path,domain,secure)
名称、值、有效期、服务器路径、域名、是否用安全的https来传输

Cookie被仿造怎么办?

建议对客户端标识的用户敏感信息数据,使用Session会话认证方式,避免被他人仿冒身份。
敏感的信息如账号密码等尽量不要写到Cookie中。最好是像Google、Baidu那样将Cookie信息加密,提交到服务器后再进行解密,保证Cookie中的信息只要本人能读得懂。而假如选择Session就省事多了,反正是放在服务器上,Session里任何隐私都能够有效的保护。

Cookie和Session的区别

  1. 数据存放位置不同:cookie数据存放在客户的浏览器上,session数据放在服务器上。
  2. 安全程度不同:cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
  3. 性能使用程度不同:session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie;cookie会附加在每个http请求中,无形增加了流量,对于大data不适用。
  4. 数据存储大小不同:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制。
  5. 浏览器支持不同:Cookie是需要客户端浏览器支持的。假如客户端禁用了Cookie,或者不支持Cookie,则会话跟踪会失效。关于WAP上的应用,常规的Cookie就派不上用场了。
  6. 跨域支持不同:Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。跨域名Cookie如今被普遍用在网络中,例如Google、Baidu、Sina等。而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。
  7. 存放数据类型不同:cookie存放的树ASCLL码表示的数据,而Session中可以保存任意类型的数据。

Session校验服务器该如何设计

session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串。
每个客户端请求都会和服务器建立一个会话,会有一个唯一的SessionId, 客户端在收到SessionId之后可以将seesionId保存(比如保存在cookie中),然后每次通过cookie的sessionId去验证。
缺点:时间较短,需要服务器设置;服务器挂了需要重新登录。
1、用户向服务器发送用户名和密码。
2、服务器验证通过后,在当前session里面保存相关数据,比如用户角色、登录时间等等。
3、服务器向用户返回一个 session_id,写入用户的 Cookie。
4、用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

Session劫持

Session劫持攻击通过窃取或预测有效的Session令牌来获得未经授权Web服务器访问权限。
Session ID应至少为128位长,以防止蛮力Session猜测攻击。

https://blog.csdn.net/qq_36031499/article/details/54573461
https://zhidao.baidu.com/question/575343552.html
https://www.cnblogs.com/hnzheng/p/12732047.html

Cache

解释下Cache的运行过程,怎么保证cache一致性

三级缓存结构cpu -> cache -> memory
缓存一致性:用于保证多个CPU cache之间缓存共享数据的一致。
MESI,则是缓存一致性协议中的一个,到底怎么实现,还是得看具体的处理器指令集。
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。更新的时候,先更新数据库,然后再删除缓存。
更新的时候,先更新数据库,然后再删除缓存。
如果不删除而是使用更新,在并发的情况下可能导致数据不一致。

Cache的算法

FIFO算法

FIFO算法的思想是先进先出(FIFO,队列),这是最简单、最公平的一种思想,即如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小。空间满的时候,最先进入的数据会被最早置换(淘汰)掉
FIFO 算法的描述:设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:
set(key,value):将记录(key,value)插入该结构。当缓存满时,将最先进入缓存的数据置换掉。
get(key):返回key对应的value值。
实现:维护一个FIFO队列,按照时间顺序将各数据(已分配页面)链接起来组成队列,并将置换指针指向队列的队首。再进行置换时,只需把置换指针所指的数据(页面)顺次换出,并把新加入的数据插到队尾即可。
缺点:判断一个页面置换算法优劣的指标就是缺页率,而FIFO算法的一个显著的缺点是,在某些特定的时刻,缺页率反而会随着分配页面的增加而增加,这称为Belady现象。产生Belady现象现象的原因是,FIFO置换算法与进程访问内存的动态特征是不相容的,被置换的内存页面往往是被频繁访问的,或者没有给进程分配足够的页面,因此FIFO算法会使一些页面频繁地被替换和重新申请内存,从而导致缺页率增加。因此,现在不再使用FIFO算法。

LRU算法

LRU(The Least Recently Used,最近最久未使用算法)的思想是:如果一个数据在最近一段时间没有被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最久没有访问的数据最先被置换(淘汰)。
LRU算法的描述: 设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:
set(key,value):将记录(key,value)插入该结构。当缓存满时,将最久未使用的数据置换掉。
get(key):返回key对应的value值。
实现:最朴素的思想就是用数组+时间戳的方式,不过这样做效率较低。因此,我们可以用双向链表(LinkedList)+哈希表(HashMap)实现(链表用来表示位置,哈希表用来存储和查找),在Java里有对应的数据结构LinkedHashMap。

LFU算法

LFU(Least Frequently Used ,最近最少使用算法)的思想是:如果一个数据在最近一段时间很少被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最小频率访问的数据最先被淘汰
LFU 算法的描述:
设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:
set(key,value):将记录(key,value)插入该结构。当缓存满时,将访问频率最低的数据置换掉。
get(key):返回key对应的value值。
算法实现策略:考虑到 LFU 会淘汰访问频率最小的数据,我们需要一种合适的方法按大小顺序维护数据访问的频率。LFU 算法本质上可以看做是一个 top K 问题(K = 1),即选出频率最小的元素,因此我们很容易想到可以用二项堆来选择频率最小的元素,这样的实现比较高效。最终实现策略为小顶堆+哈希表。

https://www.cnblogs.com/snow826520/p/8574824.html
https://www.cnblogs.com/hongdada/p/10406902.html

计算机系统架构

7层模型(OSI模型)和4层模型(TCP/IP 模型),每一层有哪些常见协议?

应用层、传输层、网络层常见协议:DNS 、 HTTP 、FTP、 STMP 、SSL、 TCP、 UDP、 ARP、 IP

路由器/交换机是哪一层

网络层

网络层用来干嘛?传输层用来干嘛?

网络层只是负责传输,把数据交给指定的目标,
传输层用来把收到的数据,根据协议分发给各个应用

怎么给大量url和ip去重

  1. 内存够用,将URL存入hash链表,每个URL读入到hash链表中,遇到重复的就舍弃,否则加入到链表里面,最后遍历得到所有不重复的URL。空间复杂度M,时间复杂度为O(N+N/M),M为不重复的URL,N为总URL数,但是M无法预测,所以存在风险,可能内存不足以存储所有的不重复URL。
  2. 为了解决内存可能不足的问题,需要把hash链表变化成普通的hash表,每个hash表元素指向一个文件文件,这个文件记录了所有该hash值对应的无重复的URL,那么在加入URL的时候就遍历对应文件中的URL,没有重复则加入到文件中。这样做时间复杂度没有提升,但是每次都要读写文件,消耗的时间应该是上一种方式的三倍(依赖于io速度),而对内存的要求比较小。一个改进是加入URL的时候进行排序,这样能减少比对的次数。

当在局域网中使用ping www.xxx.com时,用到了哪些协议?

  1. 因为ping的话 后面跟的是地址,所以要先将域名转换为ip地址,即用到了DNS
  2. 获取到ip地址后,在数据链路层是根据MAC地址传输的,所以要用到ARP解析服务,获取到MAC地址
  3. ping功能是测试另一台主机是否可达,程序发送一份ICMP回显请求给目标主机,并等待返回ICMP回显应答,(ICMP主要是用于ip主机、路由器之间传递控制信息,控制信息是指网络通不通,主机是否可达)

https://blog.csdn.net/weixin_34212762/article/details/85514043
https://www.nowcoder.com/questionTerminal/e515ae7a18924fe3b6952ae7fbb985bc

待整理问题

为什么要并发控制?

了解索引吗?知道实现原理吗?(B+树)

DNS是什么?内部如何实现?

ARP是什么?ARP内部如何实现?

Linux io模型(select, poll, epoll的区别,水平触发和边缘触发的区别)

GDB有用过哪些

谈谈你对前后端交互中使用的JSON的理解

操作系统为什么有用户态和内核态,用户级线程与内核级线程如何转换

函数调用汇编 怎么传参数 函数a call b,参数放在哪个栈帧

虚拟内存作用? 内存分页的作用?

缺页异常的介绍

OOM问题和 StackOverFlow的区别

数组怎么扩容?

新建一个更大新数组,然后复制过去……

复制的时候锁住数组,所有的操作都阻塞?

(面试之后去看了线程池里的阻塞队列,似乎都是用链表实现的,没有用数组。用到的队列似乎默认都是动态扩容的,最大为整数最大值。如果队列满了又不支持动态扩容,可以通过设置饱和策略来处理,默认是中止,也就是抛出 RejectedExecutionException。)

读写分离有什么用?

写操作都在主库,读操作都在分库,让读操作能并发,提高效率。