一、TCP的三次握手全过程
First:建立连接时,客户端发送SYN包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认。
Second:服务器收到SYN包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。
Third:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHEND状态,完成三次握手。
完成三次握手后,客户端与服务器开始传送数据。
二、死锁
1、产生死锁的原因:竞争资源和进程推进顺序非法。
2、产生死锁的必要条件:互斥条件、请求与保持条件、不剥夺条件和环路等待条件。
3、预防死锁的方法:通过摒弃死锁产生的必要条件来防止死锁发生。
4、具有代表性的避免死锁的算法:“银行家算法”。
三、读下列程序写出输出结果
#include <iostream.h>
class Base
{
public:
virtual ~Base()
{cout << "~base" << endl;}
};
class Derived : public Base
{
public:
virtual ~Derived()
{cout << "~derived" << endl;}
};
void main()
{
Base *pB = new Derived;
delete pB;
}
【输出】~derived
~base
若析构函数不是虚函数,则只输出:~base
四、进程间通信的方式有:共享内存、管道、socket、消息队列、DDE(动态数据交换)、剪贴板、邮件槽、串行/并行通信、COM/DCOM。
五、进程(线程)同步/异步总结:
1、Critical Sention:速度快、不能用于不同进程、不能进行资源统计。
2、Mutex:速度慢、可用于不同进程、不能进行资源统计。
3、Semaphore:速度慢、可用于不同进程、可进行资源统计。
4、Event:速度慢、可用于不同进程、可进行资源统计。
六、排序算法的稳定性:
稳定排序算法有:基数排序算法、冒泡排序算法、插入排序算法、归并排序算法。
不稳定排序算法有:快速排序算法、希尔排序算法、选择排序算法、堆排序算法。
七、内存拷贝函数
void* memcpy(void* pvTo, const void* pvFrom, size_t size)
{
assert((pvTo != NULL) && (pvFrom != NULL));
byte* pbTo = (byte*)pvTo;//防止改变pvTo的地址
byte* pbFrom = (byte*)pvFrom;
while(size-- > 0)
*pbTo++ = *pbFrom++;
return pvTo;
}
八、实现string类的构造函数、拷贝构造函数、析构函数以及赋值函数
{
public:
String(const char *str = NULL); // 普通构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operate =(const String &other); // 赋值函数
private:
char *m_data; // 用于保存字符串
};
请编写String的上述4个函数。
// String的普通构造函数
String::String(const char *str)
{
if(str==NULL)
{
m_data = new char[1];
*m_data = ‘0’;
}
else
{
int length = strlen(str);
m_data = new char[length+1];
strcpy(m_data, str);
}
}
// 拷贝构造函数
String::String(const String &other)
{
int length = strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data, other.m_data);
}
String::~String(void)
{
delete [] m_data;
// 由于m_data是内部数据类型,也可以写成 delete m_data;
}
// 赋值函数
String & String::operate =(const String &other)
{
// (1) 检查自赋值
if(this == &other)
return *this;
// (2) 释放原有的内存资源
delete [] m_data;
// (3)分配新的内存资源,并复制内容
int length = strlen(other.m_data);
m_data = new char[length+1];
strcpy(m_data, other.m_data);
// (4)返回本对象的引用
return *this;
}
2) 成员类对象构造函数如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序而不是它们出现在成员初始化表中的顺序;
3 )派生类构造函数
(2)通过指针可使主调函数和被调函数之间共享变量或数据结构,便于实现双向数据通讯。
(3)可以实现动态的存储分配。
(4)便于表示各种数据结构,编写高质量的程序。
{
int low = 0;
int high = n-1;
int mid;
while(low <= high)
{
mid = (high + low)/2;
if(arr[mid] > key)
high = mid - 1;
else if(arr[mid] < key)
low = mid + 1;
else
return mid;
}
return -1;
}