千辛万苦过了一面,谢谢老天保佑。
接下来的二面,主要是专访3班吴大神后加上一丁点自己的东西的成果。
=======================================
1.简单介绍下你的项目?
在这个项目中用到了技术如下:libvirt的API调用,js的ajax异步技术,进程间的通信。
学到的什么:一是网站的ajax和js编码能力的提高,二是对以前的涉及到的通信,TCP/IP协议理解更深了。
2.TCP的三次握手和四次挥手
三次握手:
======================================================
Client ----------> Server
Syn=1 Seq=a 此时Client进入了SYN_SENT状态
======================================================
Client <---------- Server
Ack=a+1 Syn=1 Seq = b 此时服务器进入了SYN_REVC状态
======================================================
Client ------------> Server
Ack=b+1 Seq = z 两者同时进入了ESTABLISHED状态
======================================================
细心的同学能够发现,只有前两次涉及到syn包了,那就涉及到什么是syn包了?
syn包是TCP连接发起的第一个信息包,它很小很小(也基于此有一个syn floor攻击),它表示握手信号。
如果提到了syn攻击:黑客发送syn包后,服务器在Syn_RECV状态,它在等待,等收到ACK后,服务器转入ESTABLISHED状态,如果没有呢?就白等了,如果白等很多回,就会耗尽服务器资源。
如果提到了怎么防范:SynAttackProtect保护机制、SYN cookies技术、在服务器增大最大连接数、缩短超时时间。
四次挥手:
======================================================
Client ----------------------> Server
Fin=1 Ack=z Seq=x 告诉Server,Client不会再传输数据过来了
======================================================
Client <---------------------- Server
Ack=x+1 Seq = z 告诉Client,Server收到
======================================================
Client <--------------------- Server
Fin=1 Ack=x Seq=y 告诉Client,Server再也不会传输数据过去了
======================================================、
Client ----------------------> Server
Ack=y Seq=x 告诉Server,Client收到
================================= =====================
为啥握手是三次、挥手是四次?
3.进程之间的通信有几种方法?它们的优缺点是什么?
3.1.其实,至今只会一种:SOCKET通信。
ss = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ss.bind((HOST,PORT))
ss.listen(5) //限定连接数为5
while True:
cs,addr = ss.accept()
cs.send("200 Connected!")
rev_data = cs.recv(BUF_SIZE)
cs.close()
Client:
cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cs.connect((HOST,PORT))
rev_data = cs.recv(BUF_SIZE)
cs.send("Hi,Server,I am Client!")
cs.close()
3.2 使用共享内存方式(Shared Memory)
HANDLE CreateFileMapping(HANDLE,LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR)
产生一个file-mapping核心对象
LPVOID MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAcess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberOfBytesToMap
);
得到共享内存的指针
b.找出共享内存
每个进程都必须有相同的能力,产生共享内存并将它初始化。
HANDLE OpenFileMapping(DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName);
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
CloseHandle();
3.3 信号量
/*
一组生产者,一组消费者,公用n个环形缓冲区。
empty——表示缓冲区是否为空,初值为n。
full——表示缓冲区中是否为满,初值为0。
mutex1——生产者之间的互斥信号量,初值为1。
mutex2——消费者之间的互斥信号量,初值为1。
*/
//生产者进程
while(TRUE){
生产一个产品;
P(empty);
P(mutex1);
产品送往buffer(in);
in=(in+1)mod n;
V(mutex1);
V(full);
}
//消费者进程
while(TRUE){
P(full)
P(mutex2);
从buffer(out)中取出产品;
out=(out+1)mod n;
V(mutex2);
V(empty);
消费该产品;
}
3.4 消息管道(Message Pipe)
匿名管道是不命名的,它最初用于在本地系统中父进程与它启动的子进程之间的通信。
就像水管连接两个地方并输送水一样,软件的管道连接两个进程并输送数据。
一个管道一旦被建立,它就可以象文件一样被访问,并且可以使用许多与文件操作同样的函数。
可以使用CreateFile函数获取一个已打开的管道的句柄,或者由另一个进程提供一个句柄。
使用WriteFile函数向管道写入数据,之后这些数据可以被另外的进程用ReadFile函数读取。
管道是系统对象,因此管道的句柄在不需要时必须使用CloseHandle函数关闭。
3.5 Internet通信
4.设计模式
4.1单例模式
public sealed class Singleton
{
static Singleton instance=null;
static readonly object padlock = new object();
Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance==null)
{
lock (padlock)
{
if (instance==null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
解决了同步问题,以及限制只能产生一个实例。
public sealed class Singleton
{
static readonly Singleton instance=new Singleton();
static Singleton()
{
}
Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
}
这样子在应用程序一跑起来就初始化成功了。
public sealed class Singleton
{
Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
实际上,该版本也是目前大多数应用程序用到的方法。
4.2简单工厂模式
/*
CPU 工厂类
*/
public interface Cpu {
public void calculate();
}
public class IntelCpu implements Cpu {
private int pins = 0;
public IntelCpu(int pins){
this.pins = pins;
}
@Override
public void calculate() {
System.out.println("Intel CPU的针脚数:" + pins);
}
}
public class AmdCpu implements Cpu {
private int pins = 0;
public AmdCpu(int pins){
this.pins = pins;
}
@Override
public void calculate() {
System.out.println("AMD CPU的针脚数:" + pins);
}
}
public class CpuFactory {
public static Cpu createCpu(int type){
Cpu cpu = null;
if(type == 1){
cpu = new IntelCpu(755);
}else if(type == 2){
cpu = new AmdCpu(938);
}
return cpu;
}
}
/*
主板 工厂类
*/
public interface Mainboard {
public void installCPU();
}
public class IntelMainboard implements Mainboard {
private int cpuHoles = 0;
public IntelMainboard(int cpuHoles){
this.cpuHoles = cpuHoles;
}
@Override
public void installCPU() {
System.out.println("Intel主板的CPU插槽孔数是:" + cpuHoles);
}
}
public class AmdMainboard implements Mainboard {
private int cpuHoles = 0;
public AmdMainboard(int cpuHoles){
this.cpuHoles = cpuHoles;
}
@Override
public void installCPU() {
System.out.println("AMD主板的CPU插槽孔数是:" + cpuHoles);
}
}
public class MainboardFactory {
public static Mainboard createMainboard(int type){
Mainboard mainboard = null;
if(type == 1){
mainboard = new IntelMainboard(755);
}else if(type == 2){
mainboard = new AmdMainboard(938);
}
return mainboard;
}
}
/*
使用工厂类来测试CPU和主板是不是兼容
*/
public class ComputerEngineer {
private Cpu cpu = null;
private Mainboard mainboard = null;
public void makeComputer(int cpuType , int mainboard){
//1:首先准备好装机所需要的配件
prepareHardwares(cpuType, mainboard);
//2:组装机器
//3:测试机器
//4:交付客户
}
private void prepareHardwares(int cpuType , int mainboard){
this.cpu = CpuFactory.createCpu(cpuType);
this.mainboard = MainboardFactory.createMainboard(mainboard);
//测试配件是否好用
this.cpu.calculate();
this.mainboard.installCPU();
}
}
4.3抽象工厂模式
public interface AbstractFactory {
//创建CPU对象
public Cpu createCpu();
//创建主板对象
public Mainboard createMainboard();
}
public class IntelFactory implements AbstractFactory {
@Override
public Cpu createCpu() {
// TODO Auto-generated method stub
return new IntelCpu(755);
}
@Override
public Mainboard createMainboard() {
// TODO Auto-generated method stub
return new IntelMainboard(755);
}
}
public class AmdFactory implements AbstractFactory {
@Override
public Cpu createCpu() {
// TODO Auto-generated method stub
return new IntelCpu(938);
}
@Override
public Mainboard createMainboard() {
// TODO Auto-generated method stub
return new IntelMainboard(938);
}
}
public class ComputerEngineer {
private Cpu cpu = null;
private Mainboard mainboard = null;
public void makeComputer(AbstractFactory af){
//1:首先准备好装机所需要的配件
prepareHardwares(af);
//2:组装机器
//3:测试机器
//4:交付客户
}
private void prepareHardwares(AbstractFactory af){
//直接找相应的工厂获取
this.cpu = af.createCpu();
this.mainboard = af.createMainboard();
//测试配件是否好用
this.cpu.calculate();
this.mainboard.installCPU();
}
}
public class Client {
public static void main(String[]args){
//创建装机工程师对象
ComputerEngineer cf = new ComputerEngineer();
//客户选择并创建需要使用的产品对象
AbstractFactory af = new IntelFactory();
//告诉装机工程师自己选择的产品,让装机工程师组装电脑
cf.makeComputer(af);
}
}
因为简单工厂模式,随着产品的增多,平级结构随之增多,整个框架就很冗余。
5.如果快速给出关键字在一组文件中出现的位置,频率
1.
建立倒排索引:关键词 && 频度 && 位置
2.
取得关键词
文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的内容为:He once lived in Shanghai.
分词加过滤后:
文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
文章2的所有关键词为:[he] [live] [shanghai]
3.
建立倒排索引
步骤2中是:“文章号”对应“文章中所有关键词”
倒排索引成:“关键词”对应“文章号”
倒排后:
关键词 文章号
guangzhou 1
he 2
i 1
live 1,2
shanghai 2
tom 1
4.
修改索引结构
关键词 文章号[出现频率] 出现位置
guangzhou 1[2] 3,6
he 2[1] 1
i 1[1] 4
live 1[2] 2,5
2[1] 2
shanghai 2[1] 3
tom 1[1] 1
lucene使用二元搜索算法快速定位关键词。
6.自然数a = b * c,怎么确定b+c的最小和
所以这道题转化成如何确定一个数的所有质因子。
记得当年写ACM的时候用过:素数筛选法!
int *prime = int[100];
count = 0;
for (i = 2; i * i <= n; i ++) {
if(n % i == 0) {
while (n % i == 0) {
prime[count] = i;
count ++;
n /= i;
}
}
}
貌似有更快的算法,用到了分解多项式,具体不清楚。
7.一串数字,有一个数字占了一半以上,怎么确定这个数?
8.请对百度文库的“登录”进行测试
9.请对一个3楼的电梯进行测试,该电梯每层只有一个up按钮,down按钮
10.请对百度搜索框的搜索建议进行测试
数目是否在控制范围内:10?
文字大小?颜色?
长度?
内容相关程度?
是否即时更新?
是否有纠正功能?
是否是百度产品优先出现?
是否是敏感词汇?
当时我就只想到这么多。。有更多的请回复。我加上。