oppo校招笔试题

题型:选择题(单选和多选)+问答题+编程题(2道)

问答题:

1.简述一下TCP三次握手,为什么是三次握手?

(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
  (2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
  (3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

为什么是三次握手?

为什么连接建立需要三次握手,而不是两次握手?
防止失效的连接请求报文段被服务端接收,从而产生错误。

PS:失效的连接请求:若客户端向服务端发送的连接请求丢失,客户端等待应答超时后就会再次发送连接请求,此时,上一个连接请求就是『失效的』。

若建立连接只需两次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入ESTABLISHED状态,而服务端在收到连接请求后就进入ESTABLISHED状态。此时如果网络拥塞,客户端发送的连接请求迟迟到不了服务端,客户端便超时重发请求,如果服务端正确接收并确认应答,双方便开始通信,通信结束后释放连接。此时,如果那个失效的连接请求抵达了服务端,由于只有两次握手,服务端收到请求就会进入ESTABLISHED状态,等待发送数据或主动发送数据。但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端连接资源。
作者:大闲人柴毛毛
链接:https://www.zhihu.com/question/24853633/answer/254224088
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

SYN攻击:
  在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:
  #netstat -nap | grep SYN_RECV

生产者消费者代码:

public class ShengchanzheXiaofeizhe {
	private final int MAX_SIZE;
	private int count;
	public ShengchanzheXiaofeizhe(int n){
		MAX_SIZE=n;
		count=0;
		
	}
	public synchronized void add(){
		while(count>=MAX_SIZE){
			System.out.println("仓库已经满了");
			try{
				this.wait();
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
		count++;
		System.out.println(Thread.currentThread().toString()+"put"+count);
		this.notifyAll();
	}
	public synchronized void remove(){
		while(count<=0){
			System.out.println("仓库已经空了");
			try{
				this.wait();
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
		
		
		System.out.println(Thread.currentThread().toString()+"get"+count);
		count--;
		this.notify();
	}
	public static void main(String []args){
		ShengchanzheXiaofeizhe s=new ShengchanzheXiaofeizhe(5);
		Thread pro=new Producer(s);
		Thread con=new Consumer(s);
		Thread pro2=new Producer(s);
		Thread con2=new Consumer(s);
		pro.setName("生产者1");
		pro2.setName("生产者2");
		con.setName("消费者1");
		con2.setName("消费者2");
		pro.start();
		pro2.start();
		con.start();
		con2.start();
	}

}
class Producer extends Thread{
	private ShengchanzheXiaofeizhe s;
	public Producer(ShengchanzheXiaofeizhe s){
		this.s=s;
		
	}
	public void run(){
	while(true){
		s.add();
		try{
			Thread.sleep(1000);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
	}
}
class Consumer extends Thread{
	private ShengchanzheXiaofeizhe s;
	public Consumer(ShengchanzheXiaofeizhe s){
		this.s=s;
		
	}
	public void run(){
	while(true){
		s.remove();
		try{
			Thread.sleep(1500);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
	}
}

随机产生10个数字比如(12,32,2323,...10),变成(21,23,3232,....1),再降序输出。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class OPPO01 {
	public static void main(String[] args) {
		int[] s1=randomNumber(1,1000,10);
		int[] s2=new int[10];
		for(int i=0;i<10;i++){
			int temp=0;
			s2[i]=0;
			while(s1[i]/10!=0){
				temp=s1[i]%10;
				s2[i]=(s2[i]+temp)*10;
				s1[i]=s1[i]/10;
			}
			s2[i]=s2[i]+s1[i]%10;
		}
		
		sort(s2);
		for(int i=0;i<10;i++){
			System.out.println(s2[i]);
		}
	}
	public static int[] sort(int[] s){
		for(int i=1;i<s.length;i++){
			int j;
			int e=s[i];
			for(j=i-1;j>=0&&s[j]<e;j--){
				
				s[j+1]=s[j];
			}
			s[j+1]=e;
		}
		return s;
		
	}


public static int[] randomNumber(int min,int max,int n){

    //判断是否已经达到索要输出随机数的个数
    if(n>(max-min+1) || max <min){
        return null;
    }

    int[] result = new int[n]; //用于存放结果的数组

    int count = 0;
    while(count <n){
        int num = (int)(Math.random()*(max-min))+min;
        boolean flag = true;
        for(int j=0;j<count;j++){
            if(num == result[j]){
                flag = false;
                break;
            }
        }
        if(flag){
            result[count] = num;
            count++;
        }
    }
    return result;
} 
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值