字节一面

字节后端一面(暑期实习)

1. 网络相关

1.1为什么upd不可靠

UDP(User Data Protocol,用户数据报协议)是无连接的、简单的、面向数据报的传输层协议。也就是 UDP 在发送数据之前,无须建立客户端与服务端的连接,直接发送消息即可。
TCP可靠数据传输原理
每个Tcp socket在内核中都有一个发送缓冲区和一个接受缓冲区。tcp协议要求对端在接受到tcp数据报之后,要对其序号进行ACK,只有当接受到一个tcp数据报的ACK之后,才可以把这个tcp数据报从socket的发送缓冲区清除,另外tcp还有一个流量控制功能,tcp的socket接受缓冲区接受到网络上来的数据缓存起来后,如果应用程序一直没有读取,
socket接受缓冲区满了之后,发生的动作是:通知对端TCP协议中的窗口关闭,这便是滑动窗口的实现,保证TCP socket接受缓冲区不会溢出,因为对方不允许发送超过所通知窗口大小的数据, 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。这两点保证了tcp是可靠传输的。
UDP不可靠数据传输原理
UDP只有一个socket接受缓冲区,没有socket发送缓冲区,即只要有数据就发,不管对方是否可以正确接受。而在对方的socket接受缓冲区满了之后,新来的数据报无法进入到socket接受缓冲区,此数据报就会被丢弃,udp是没有流量控制的,故UDP的数据传输是不可靠的。

1.2为什么tcp要三次握手,两次不行吗

在这里插入图片描述

  • 为了防止旧的重复连接引起连接混乱问题
    比如在网络状况比较复杂或者网络状况比较差的情况下,发送方可能会连续发送多次建立连接的请求。如果 TCP 握手的次数只有两次,那么接收方只能选择接受请求或者拒绝接受请求,但它并不清楚这次的请求是正常的请求,还是由于网络环境问题而导致的过期请求,如果是过期请求的话就会造成错误的连接。
    所以如果 TCP 是三次握手的话,那么客户端在接收到服务器端 SEQ+1 的消息之后,就可以判断当前的连接是否为历史连接,如果判断为历史连接的话就会发送终止报文(RST)给服务器端终止连接;如果判断当前连接不是历史连接的话就会发送指令给服务器端来建立连接。
    在这里插入图片描述
  • 同步初始化序列化
    客户端和服务端双方在建立TCP连接并初始化序列号(ISN),使用随机生成算法生成,不能设置为一个固定值,因为这样容易被攻击者猜出后续序列号。
    TCP 为了保证在不稳定的网络环境中构建一个稳定的数据连接,它就需要一个“序列号”字段来保证自己的稳定性,而这个序列号的作用就是防止数据包重复发送,以及有效的解决数据包接收时顺序颠倒的问题。那么在建立 TCP 连接时就需要同步初始化一个序列号来保证 TCP 的稳定性.

●首先客户端发送一个携带了初始序列号的 SYN 报文给服务器端;
●服务端接收到消息之后会回复一个 ACK 的应答报文,表示客户端的 SYN 报文已被服务端成功接收了;
●而客户端收到消息之后也会发送一个 ACK 给服务端,服务器端拿到这个消息之后,我们就可以得到一个可靠的初始化序列号了。

如果是两次握手的话,就无法进行序列号的确认工作了,因此也就无法得到一个可靠的序列号了

1.3输入网站地址访问的过程

  1. 在客户端浏览器中输入网址URL。

  2. 发送到DNS(域名服务器)获得域名对应的WEB服务器的IP地址。

  3. 客户端浏览器与WEB服务器建立TCP(传输控制协议)连接。

  4. 客户端浏览器向对应IP地址的WEB服务器发送相应的HTTP或HTTPS请求。

  5. WEB服务器响应请求,返回指定的URL数据或错误信息;如果设定重定向,则重定向到新的URL地址。

  6. 客户端浏览器下载数据,解析HTML源文件,解析的过程中实现对页面的排版,解析完成后,在浏览器中显示基础的页面。

  7. 第七步:浏览器请求样式以及图片文件,用以渲染界面并显示给用户

2. session和cookie

2.1有什么区别

Cookie机制是通过检查客户身上的“通行证”来确定客户身份,存储在用户浏览器端;Session机制是通过检查服务器上的“客户明细表”来确认客户身份,存储在服务器端。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

2.2知道cookie怎么运行吗

1、cookie的创建:服务端通过Set-Cookie的http头要求客户端创建,并给予其规定生命长度
2、cookie的使用:客户端每次请求都会根据path、domain通过Cookie的http头将cookie信息传送给服务端

Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

3.操作系统

3.1进程,线程,协程分别介绍

1、进程

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。

2、线程

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。

3、协程

协程是一种用户态的轻量级线程,不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行),完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
用户控制让协程暂停,和线程的阻塞是有本质区别的。协程的暂停完全由程序控制,线程的阻塞状态是由操作系统内核来进行切换因此,协程的开销远远小于线程的开销。

3.2不同进程怎么通信

1.管道
2.消息队列
注意,此消息队列不是我们常用的MQ,如kafka,rabbitmq,rocketmq等。消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。
使用消息队列进行进程间通信,可能会收到数据块最大长度的限制约束等,这也是这种通信方式的缺点。如果频繁的发生进程间的通信行为,那么进程需要频繁地读取队列中的数据到内存,相当于间接地从一个进程拷贝到另一个进程,这需要花费时间。

3.共享内存
共享内存这个通信方式就可以很好着解决拷贝所消耗的时间了。系统加载一个进程的时候,分配给进程的内存并不是实际物理内存,而是虚拟内存空间。那么我们可以让两个进程各自拿出一块虚拟地址空间来,然后映射到相同的物理内存中,这样,两个进程虽然有着独立的虚拟内存空间,但有一部分却是映射到相同的物理内存,这就完成了内存共享机制了。

4.信号量
共享内存最大的问题是什么?没错,就是多进程竞争内存的问题,就像类似于我们平时说的线程安全问题。如何解决这个问题?这个时候我们的信号量就上场了。
信号量的本质就是一个计数器,用来实现进程之间的互斥与同步。例如信号量的初始值是 1,然后 a 进程来访问内存1的时候,我们就把信号量的值设为 0,然后进程b 也要来访问内存1的时候,看到信号量的值为 0 就知道已经有进程在访问内存1了,这个时候进程 b 就会访问不了内存1。所以说,信号量也是进程之间的一种通信方式。

5.Socket
这个就是我们一直在用的进程间的通信方式了,如我们的微信APP跟微信服务器通信,其实就是使用的Socket套接字进行通信的。

4.java

4.1介绍一下多态

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

**4.2多态怎么运行不同方法

4.3静态绑定和动态绑定

4.4ArrayList和LinkedList区别**

均为线程不安全,想在多线程下使用,应该使用Colletions类中的静态方法synchronizedList()对其进行调用。

private List<String> synchronizedList = 
	Collections.synchronizedList(new ArrayList<>());

ArrayList内部是使用一个数组来存放对象,方便查找和随机访问,但是不方便增删,因为增删会导致被操作位后面的所有内容都进行移动。无参构造时初始10位,每次扩容1.5倍,删除数据时不会自动缩容,可调用方法缩容。

`  public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = Arrays.copyOf(elementData, size);
        }
    }`

LinkedList底层采用双向链表,记录first,last头尾节点。方便增删,但是无法随机访问,查找采用二分查找。在这里插入图片描述

在这里插入图片描述

5.算法

5.1单链表在目的位置插入节点

使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。

bool IsExitsLoop(slist *head) 
{ 
     slist *slow = head, *fast = head; 
   
     while ( fast && fast->next )  
     { 
         slow = slow->next; 
         fast = fast->next->next; 
         if ( slow == fast ) break ; 
     } 
   
     return !(fast == NULL || fast->next == NULL); 
}

5.2单链表环怎么找到入口

碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。

slist* FindLoopPort(slist *head) 
{ 
     slist *slow = head, *fast = head; 
   
     while ( fast && fast->next )  
     { 
         slow = slow->next; 
         fast = fast->next->next; 
         if ( slow == fast ) break ; 
     } 
   
     if (fast == NULL || fast->next == NULL) 
         return NULL; 
   
     slow = head; 
     while (slow != fast) 
     { 
          slow = slow->next; 
          fast = fast->next; 
     } 
   
     return slow; 
}
//C语言函数传参又忘了,复习:
//https://www.cnblogs.com/51try-again/p/10206374.html

5.3数组中有一个数出现超过一半,如何找到

public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        //养成好的习惯,开始的时候一定要判断为空的情况
        if(array==null||array.length==0)
        {
            return 0;
        }
        //Boyer-Moore Majority Vote Algorithm算法
        //找到序列中出现次数最多的元素
        int most=array[0];
        int count=1;
        for(int i=1;i<array.length;i++)
        {
            count=most==array[i]?count+1:count-1;
            if(count==0)
            {
                most=array[i];
                count=1;
            }
        }
        //判断题目的条件,看是否出现次数超过了一半
        count=0;
        for(int i=0;i<array.length;i++)
        {
            if(most==array[i])
            {
                count++;
            }
        }
        return count>array.length/2?most:0;
    }
}

5.4逻辑题:70g盐20g砝码称5g盐最少次数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值