**
这篇文章内容是我自己整理的,大概是面试中不太了解的内容和常考的题目。我自己总结的,分享给大家!
**
———-
TCP建立连接3次握手:
建立连接时server的SYN ACK如没有被client接到,那么会有超时重传,默认5次 63s
Syn攻击:重复确认包攻击
如果SYN确认队列满了,那么servre会发送一个确认synccookie,正常连接会返回回来
断开连接时,client不会立即关闭而是等待2msl :
(1)等待确认server收到了关闭的ack,如果没收到,server会重新请求,一来一回正好2MSL
Linux是 30s长度的msl 标准是 2min
(2)确保网络彻底干净 不会有残留tcp包
Ack重传方式
(1)死等,直到超时重传(2)快重传,server 3次重传相同ack则client重新发送未到的包。(3)sack确认,汇报收到的数据报碎片。
Tcp round trip time(TCP往返时间)
基于网络发送返回时间进行优化,取得一个平滑值。以便设置时间
拥塞避免,滑动窗口大小设置算法:
慢开始:小于门限值,乘法增大;
拥塞避免:大于门限制,加法增大
快恢复:发生拥塞,门限制减小一半(乘法减小),从门限制开始拥塞避免(加法增大)
快恢复前提是快重传3次相同ACK 因为网络很可能没有拥塞,所以不必慢开始
快重传(已提):3次相同ack则重传,避免等待超时重传
UDP
面向无连接,尽最大可能交付。TCP是电话 UDP是短信
7层网络:会话层表示层
表示层:将应用层转换到2进制字符
会话层:加密技术
Socket:
http://www.cnblogs.com/L-hq815/archive/2012/07/09/2583043.html
Bind:
你可能要将套接字和机器上的一定的端口关联 起来。
Connect:
连接到远程主机
listen:
等待接入请求并且用各种方法处理
accept:
连接将加入到等待接受的队列 中。调用 accept() 连接。它将返回一个新的套接字
send recv:
调用 accept() 连接。它将返回一个新的套接字,这样你就有两个套接字了,原来的一个还在侦听你的那个端口, 新的在准备发送 (send()) 和接收 ( recv()) 数据
sendto() 和 recvfrom()函数:
面向无连接,需要目标地址
close()和shutdown():
关闭,以及带参数关闭
阻塞:
sleep,非不断的查询减少cpu负载,socket默认阻塞。阻塞的一般是挂起,等缓存。非阻塞则会立即响应一个如同标识的 错误
select()–多路同步 I/O:
避免忙等select() 让你可以同时监视多个套接字。如果你想知道的话,那么它就 会告诉你哪个套接字准备读,哪个又准备写,哪个套接字又发生了例外
七状态图
http://www.2cto.com/os/201412/358908.html
HTTP:
客户端:
打开HTTP连接,建立新的连接
初始化请求
设置请求
发送请求
服务器:
读取请求,调用servelet
调用方法
初始化响应方法
设置HTTP响应
发送响应
关闭连接
加密算法
Rsa: 将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
Aes:
在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。
Hash:
用于验证数据完整性,不可逆运算确保只能正向生成HASH值进行比较,以确定数据完整性
常用 md5(已被破解,山大女教授)
p_thread\thread类
join等待子线程,detach 分离子线程
mutex成员用于加锁(进行操作前)解锁(操作后)
runnable\thread:
一个是多个线程分别完成自己的任务(thread类)
一个是多个线程共同完成一个任务(runnable接口)。
https:
1.浏览器将自己支持的一套加密规则发送给网站。
2.网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
3.获得网站证书之后浏览器要做以下工作:
a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。
b) 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
c) 使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。
4.网站接收浏览器发来的数据之后要做以下的操作:
a) 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
b) 使用密码加密一段握手消息,发送给浏览器。
5.浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
Grep:
http://www.jb51.net/article/31207.htm
awk:
http://blog.csdn.net/cuijianzhongswust/article/details/6870813
赛马问题
25马5跑道:只决出前三,8场就够了
36马 6跑道:一共8次
64匹马,8条跑道:取前四 15次
c++实现 string类:
**class MyString {
private:
char *m_data;
public:
MyString();
MyString(const char* ptr);
MyString(const MyString& rhs);
~MyString();
MyString& operator=(const MyString& rhs);
MyString operator+(const MyString& rhs);
char operator[](const unsigned int index);
bool operator==(const MyString& rhs);
friend ostream& operator<<(ostream& output, const MyString &rhs);
};
//默认的构造函数
MyString::MyString() {
m_data = new char[1];
*m_data = '\0';
}
//拷贝构造函数
MyString::MyString(const MyString& rhs) {
int len = strlen(rhs.m_data);
m_data = new char[len + 1];
strcpy(m_data, rhs.m_data);
}
//赋值操作符
MyString& MyString::operator =(const MyString& rhs) {
if (this != &rhs) {
delete[] m_data;
m_data = new char[strlen(rhs.m_data) + 1];
strcpy(m_data, rhs.m_data);
}
return *this;
}
//重载运算符+
MyString MyString::operator+(const MyString &rhs) {
MyString newString;
if (!rhs.m_data)
newString = *this;
else if (!m_data)
newString = rhs;
else {
newString.m_data = new char[strlen(m_data) + strlen(rhs.m_data) + 1];
strcpy(newString.m_data, m_data);
strcat(newString.m_data, rhs.m_data);
}
return newString;
}
//析构函数
MyString::~MyString() {
delete[] m_data;
}**
概率论 、、多继承 、、虚函数、、 虚基类 、、控制模版实例化
数组逆序对(剑指原题,不好理解)
最长递增子序列:
DP, n^2时间复杂度。
int dp[31]; /* dp[i]记录到[0,i]数组的LIS */
int lis; /* LIS 长度 */
int LIS(int * arr, int size)
{
for(int i = 0; i < size; ++i)
{
dp[i] = 1;
for(int j = 0; j < i; ++j)
{
if(arr[i] > arr[j] && dp[i] < dp[j] + 1)
{
dp[i] = dp[j] + 1;
if(dp[i] > lis)
{
lis = dp[i];
}
}
}
}
return lis;
}
每加入一个新元素就计算当前最长子序列长度。储存在数组中。
如果需要打印,可以增加一个前驱数组,保存前驱。
最长连续递增子序列:
一次遍历,保存最大和以及下标,并更新最大和和下标。
最大连续和子序列:
http://blog.sina.com.cn/s/blog_6d0d2ed10100t87t.html
最大子序列是要找出由数组成的一维数组中和最大的连续子序列。比如{5,-3,4,2}的最大子序列就是 {5,-3,4,2},它的和是8,达到最大;而 {5,-6,4,2}的最大子序列是{4,2},它的和是6。你已经看出来了,
找最大子序列的方法很简单,只要前i项的和还没有小于0那么子序列就一直向后扩展,否则丢弃之前的子序列开始新的子序列,同时我们要记下各个子序列的和,最后找到和最大的子序列。
代码如下:
1. int MaxSubSeq(const int *arr,int len,int *start,int *end){
2. int max=0; //记录目前找到的最大子序列的和
3. int sum=0; //记录当前子序列的和
4. int begin=0,finish=0; //记录当前子序列的起始下标
5. *start=begin;*end=finish; //记录最长子序列的起始下标
6. for(int i=0;i<len;i++){
7. sum+=arr[i];
8. finish=i;
9. if(sum>max){
10. max=sum;
11. *end=finish;
12. *start=begin;
13. }
14. if(sum<=0){
15. sum=0;
16. begin=i+1;
17. }
18. }
19. return max;
20. }
字符串Kmp,模式匹配
最长回文字符串
http://blog.163.com/zhaohai_1988/blog/static/2095100852012716105847112/
最长公共子序列(非连续):
for(i = 1; i <= x_len; i++)
{
for(j = 1; j <= y_len; j++)
{
if(str1[i - 1] == str2[j - 1])//匹配,则取左上元素
{
arr[i][j] = arr[i - 1][j - 1] + 1;
}
else//失配则去上或者左最大值,即以串1或者串2为基准,取当前能匹配的最大值
{
if(arr[i][j - 1] >= arr[i - 1][j])
{
arr[i][j] = arr[i][j - 1];
}
else
{
arr[i][j] = arr[i -1][j];
}
}
}
}
最长连续公共子序列:
#include <iostream>
#include <string>
using namespace std;
int i, j;
int len1, len2;
void getLCString(string str1, string str2)
{
len1 = str1.length();
len2=str2.length();
int maxLen = len1 > len2 ? len1 : len2;
int max[maxLen];
int maxIndex[maxLen];
int c[maxLen]; // 记录对角线上的相等值的个数
for(i=0; i<maxLen; ++i)
{
max[i]=0;
maxIndex[i]=0;
c[i]=0;
}
for (i = 0; i < len2; i++)
{
for (j = len1 - 1; j >= 0; j--)//为何倒序遍历:因为数组中存储的是上一行的情况,如果正序遍历就会覆盖掉上个状态的结果。
{
if (str2[i] == str1[j])
{
if ((i == 0) || (j == 0))
c[j] = 1;
else
c[j] = c[j - 1] + 1;
}
else
{
c[j] = 0;
}
if (c[j] > max[0]) // 如果是大于那暂时只有一个是最长的,而且要把后面的清0;
{
max[0] = c[j]; // 记录对角线元素的最大值,之后在遍历时用作提取子串的长度
maxIndex[0] = j; // 记录对角线元素最大值的位置
for (int k = 1; k < maxLen; k++)
{
max[k] = 0;
maxIndex[k] = 0;
}
}
else if (c[j] == max[0]) // 有多个是相同长度的子串
{
for (int k = 1; k < maxLen; k++)
{
if (max[k] == 0)
{
max[k] = c[j];
maxIndex[k] = j;
break; // 在后面加一个就要退出循环了
}
}
}
}
}
for (j = 0; j < maxLen; j++)
{
if (max[j] > 0)
{
cout<<"第" <<(j + 1) <<"个公共子串:"<<endl;
for (i = maxIndex[j] - max[j] + 1; i <= maxIndex[j]; i++)
cout<<str1[i]<<" ";
cout<<endl;
}
}
}
int main()
{
string str1="123456abcd567";
string str2="234dddabc45678";
getLCString(str1, str2);
return 0;
}
LCS变形
给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串(LCS变形):
将数组倒置,然后计算最长公共子串长度,用串长做差,即为需要插入的元素数量