socket网络编程(一):socket介绍及函数原语
一、socket概述
socket计算机中的一种网络传输机制,对TCP和UDP的封装,自动帮我们在底层完成各种协议操作,接收到数据包后返回到上层应用。
socket分为客户端和服务端,它的工作模型为:
socket计算机中的一种网络传输机制,对TCP和UDP的封装,自动帮我们在底层完成各种协议操作,接收到数据包后返回到上层应用。
socket分为客户端和服务端,它的工作模型为:
select模型是socket中的一种多路IO复用模型之一,通过轮询的方式来完成多路访问控制。
一个很简单的例子来描述select模型:
幼儿园老师要照顾所有的小朋友,每天他都会轮流去问小朋友:“小朋友小朋友,你饿了吗?”
如果小朋友饿了,那么老师就给这个小朋友喂饭,否则就开始询问下一个朋友,一直循环下去直到放学。
同时,如果班级里有其他的同学来了,也把他加到询问队列。如果有哪个同学生病了,则把它踢出询问队列。
select模型的原理就是这样,把所有连接的客户端socket加入到一个集合中去,然后一直不断轮询,判断哪一个socket有数据到达,就读取数据。否则继续轮询下一个数据。
linux系统在编译的时候就固定了select模型文件描述符集合的大小为1024个,这个大小无法更改,因此,select模型只适用于并发量小于1024个的服务连接。
> grep "FD_SETSIZE" /usr/include/ -R
/usr/include/linux/posix_types.h:#define __FD_SETSIZE 1024
TCP协议的三次握手和四次挥手分别表示了TCP连接的建立和释放过程,在整个TCP协议是一个很重要的内容,同时也是面试时的常见考点。
趁着找工作的劲,使用socket+tcpdump
分析了一下工作流程,socket客户端代可以在socket介绍及函数原语找到。服务端的代码可以在socket的select模型找到。
socket中各函数对应的TCP状态演示图:
速成案例:tcpdump速成指南
最简单的用法就是直接输入tcpdump
,监控所有的数据包:
[ma@ma ~]$ tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on usbmon1, link-type USB_LINUX_MMAPPED (USB with padded Linux header), capture size 65535 bytes
10:53:08.002434 CONTROL SUBMIT to 1:2:0
10:53:08.004461 CONTROL COMPLETE from 1:2:0
10:53:08.004502 CONTROL SUBMIT to 1:1:0
10:53:08.004502 CONTROL COMPLETE from 1:1:0
10:53:10.850080 CONTROL SUBMIT to 1:1:0
10:53:10.850102 CONTROL COMPLETE from 1:1:0
面向对象的三大基本特征:封装、继承和多态。类对象通过public/private/protected
关键字实现对象的封装,封装后通过继承实现多样性,而这个多样性又需要通过多态来完成。
假设要实现一个攻击的功能,不同的角色战斗力的都不同,在以往的c中,要完成这个功能需要对每个不同的角色都添加一个攻击函数:
void attack_normal(obj n) { cout << "我砍了你一刀,你流了一滴血!" << endl;}
void attack_vip(obj v) { cout << "我是VIP,我的刀是屠龙宝刀,你流了十滴血!" << endl;}
void attack_rmb(obj r) { cout << "我是RMB玩家,你已经死了!" << endl; }
而在有多多态后,所有的函数都可以合并为一个:
void attack(obj *o) {
// 根据对象o的实际类型,攻击敌方。
}
定义以下类:
class A{
public:
A(): A(0) { }
A(int i){
cout << "A(" << i << ")" << endl;
};
A(int i, int j){
cout << "A("<< i << ", " << j << ")" << endl;
}
};
定义一个简单的类:
class A{
public:
A(){
cout << "A()" << endl;
}
~A(){
cout << "~A()" << endl;
}
}
使用malloc/free
和new/delete
分别创建和释放对象:
#include<iostream>
#include<stdlib.h>
using namespace std;
int main{
cout << "---malloc/free---" << endl;
A *a1 = (A*)malloc(sizeof(A));
free(a1);
cout << "---new/delete---" << endl;
A *a2 = new A;
delete a2;
return 0;
}
运行:
---malloc/free---
---new/delete---
A()
~A()
可见,malloc
确实没有调用构造函数,free
也没有调用析构函数。
delete
和new
对应,delete[]
和new[]
对应。delete
用来删除单个对象,delete[]
删除对象数组。
delete
和delete[]
的区别在于后者会调用数组内每一个元素的析构函数,而delete只会调用一个。两者在对于内置元素类型时功能一致,对于复杂类型delete
可能会报错。
int main(){
cout << "------" << endl;
int *p1 = new int[10];
delete p1;
cout << "---delete[]---" << endl;
A *a2 = new A[1];
delete []a2;
cout << "---delete---" << endl;
A *a1 = new A[1];
delete a1;
return 0;
}
执行会报错:
可见,对内置类型而言,互相使用并没有问题。但是对自定义类型而言,delete和delete[]并不能乱用。
面试题一道:
以下数据声明都代表什么含义:
float(**def)[10];
double*(*gh)[10];
double(*f[10])();
int*((*b)[10]);
long (*fun)int;
int (*(*f)(int, int))(int);
一道需要很小心的面试题,主要考了指针数组
、数组指针
以及函数指针
的概念。
HTTP状态码一共有五大类:1xx
, 2xx
, 3xx
, 4xx
, 5xx
。
各个大类的含义如下: