文章目录
- 一、概念
- (一)网络发展阶段
- 1. ARPAnet阶段
- 2. TCP/IP两个协议阶段
- 3. 网络体系结构和OSI开放系统互联模型
- 4. TCP/IP协议簇体系结构
- (1) 应用层:
- (2)传输层:
- (3)网络层:
- (4)链路层:
 
 
- (二)TCP和UDP的异同
- (三)网络基础知识
- 1. 字节序
- (1)实现将四字节无符号整型转为大端字节序功能
- (2)字节序转换函数
 
- 2. socket
- (1)概念
- (2)类型
 
- 3. IP地址
- 4. 端口号
 
- (四)虚拟机的NAT模式和桥接模式
 
一、概念
协议:通信的双方都遵循的,如何发送数据以及接到数据后如何解析的一个规则。
 网络体系结构:指网络的层次结构和每层所使用协议的集合
(一)网络发展阶段
1. ARPAnet阶段
早期的ARPAnet使用网络控制协议(Network Control Protocol,NCP),
 不能互联不同类型的计算机和不同类型的操作系统,没有纠错功能
2. TCP/IP两个协议阶段
TCP/IP协议分成了两个不同的协议:
 用来检测网络传输中差错的 传输控制协议TCP
 专门负责对不同网络进行互联的 互联网协议IP
3. 网络体系结构和OSI开放系统互联模型
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层
4. TCP/IP协议簇体系结构
对OSI开放系统模型做了简化
 
(1) 应用层:
HTTP(Hypertext Transfer Protocol) 超文本传输协议
 万维网的数据通信的基础
FTP(File Transfer Protocol) 文件传输协议
 是用于在网络上进行文件传输的一套标准协议,使用TCP传输
TFTP(Trivial File Transfer Protocol) 简单文件传输协议
 是用于在网络上进行文件传输的一套标准协议,使用UDP传输
SMTP(Simple Mail Transfer Protocol) 简单邮件传输协议
 一种提供可靠且有效的电子邮件传输的协议
(2)传输层:
TCP(Transport Control Protocol) 传输控制协议
 是一种面向连接的、可靠的、基于字节流的传输层通信协议
UDP(User Datagram Protocol) 用户数据报协议
 是一种无连接、不可靠、快速传输的传输层通信协议
(3)网络层:
IP(Internetworking Protocol) 网际互连协议
 是指能够在多个不同网络间实现信息传输的协议
ICMP(Internet Control Message Protocol) 互联网控制信息协议
 用于在IP主机、路由器之间传递控制消息----ping命令使用的协议
IGMP(Internet Group Management Protocol) 互联网组管理
 是一个组播协议,用于主机和组播路由器之间通信
(4)链路层:
ARP(Address Resolution Protocol) 地址解析协议
 通过IP地址获取对方mac地址
RARP(Reverse Address Resolution Protocol) 逆向地址解析协议
 通过mac地址获取ip地址
(二)TCP和UDP的异同
相同点:
 同为传输层的协议
不同点:
 TCP:有连接,可靠
 UDP:无连接,不保证可靠
TCP(即传输控制协议):
 是一种面向连接的传输层协议,它能提供高可靠性通信
 (即数据无误、数据无丢失、数据无失序、数据无重复到达的通信)
UDP(User Datagram Protocol)用户数据报协议:
 是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。
(三)网络基础知识
1. 字节序
不同类型CPU的主机中,内存存储多字节整数序列有两种方法,称为主机字节序(HBO):
 小端序(little-endian) - 低序字节存储在低地址
 将低字节存储在起始地址,称为“Little-Endian”字节序,Intel、AMD等采用的是这种方式;
 大端序(big-endian)- 高序字节存储在低地址
 将高字节存储在起始地址,称为“Big-Endian”字节序,由ARM、Motorola等所采用
- 注:为了保证收发数据的一致性,就发明了网络字节序(大端序) 。发送方发送数据时,需要先把数据转成网络字节序再发送,接收方接到的数据默认都认为是网络字节序的数据,需要转成主机字节序再处理。
(1)实现将四字节无符号整型转为大端字节序功能
#include <stdio.h>
//判断本主机是大端还是小端
union _num
{
    int a;
    char b;
};
int if_big_1(void){
    union _num num;
    num.a = 0x12345678;
    return (0x12 == num.b)?1:0;
}
/***第二种判断主机是大端还是小端的方法***/
int if_big_2(void){
    int num = 0x12345678;
    char *p = (char *)#
    return (0x12 == *p)?1:0;
}
int my_htonl(int num){
    if(!if_big_1()){
        //如果是小端字节序,需要转成大端字节序
        char *p = (char *)#
        char *q = p+3;
        char temp=0;
        //第0位和第3位交换
        temp = *p;
        *p = *q;
        *q = temp;
        //第1位和第2位交换
        p++;
        q--;
        temp = *p;
        *p = *q;
        *q = temp;
    }
    return num;
}
int main(int argc, char const *argv[])
{
    int num = 0x12345678;
    if(!if_big_2()){
        printf("本机为小端存储,%#x-->%#x\n",num, my_htonl(num));
    }else{
        printf("本机为大端存储,%#x-->%#x\n",num, my_htonl(num));
    }
    return 0;
}
(2)字节序转换函数
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);  //主机转网络4字节
uint16_t htons(uint16_t hostshort); //主机转网络2字节
uint32_t ntohl(uint32_t netlong);   //网络转主机4字节
uint16_t ntohs(uint16_t netshort);  //网络转主机2字节
// h  host 主机  to  转换  n  network 网络  l  四字节  s 二字节
- 注:
 1.如果明确知道收发双方的主机字节序一致,可以不考虑字节序问题
 2.多字节的整形序列需要考虑字节序的问题 (字符串可以不考虑)
2. socket
套接字通信是进程间(而非主机之间)通信的方式的一种。
(1)概念
socket是一个函数,会返回一个文件描述符,用户可以通过传参的方式指定收发数据时需要封装和解析什么协议。
socket并不仅限于linux,也并不限于TCP/IP协议族体系结构
(2)类型
流式套接字(SOCK_STREAM)----给TCP用的
 提供了一个面向连接、可靠的数据传输服务,数据无差
 错、无重复的发送且按发送顺序接收。内设置流量控制,
 避免数据流淹没慢的接收方。数据被看作是字节流,
 无长度限制。
数据报套接字(SOCK_DGRAM)----给UDP用的
 提供无连接服务。数据包以独立数据包的形式被发送,
 不提供无差错保证,数据可能丢失或重复,顺序发送,
 可能乱序接收。
原始套接字(SOCK_RAW)
 可以对较低层次协议如IP、ICMP直接访问。
3. IP地址
局域网内部使用MAC地址通信,如果使用互联网,必须用IP地址
IP地址的表示形式 “192.168.80.10” 这种叫做点分十进制,是一个字符串
 计算机中存储IP地址是用的无符号4字节整型。unsigned int
#include <my_head.h>
int is_big(void){
    int num = 0x12345678;
    char *p = (char *)#
    return (0x12 == *p)?1:0;
}
int incept_char(char *p,char *str){
    int i=0;
    while('.' != *p&& '\0' != *p){
        str[i]=*(p++);
        i++;
    }
    return i;//返回.的坐标位置
}
int main(int argc, char const *argv[])
{
    if(2 != argc){
        printf("Usage:%s IPv4\n",argv[0]);
        exit(-1);
    }
    //截取字符串
    char str1[4]={0};
    char str2[4]={0};
    char str3[4]={0};
    char str4[4]={0};
    
    char p[20]={0};
    strcpy(p,argv[1]);
    int i=0,j=0;
    j = incept_char(p,str1);
    i=i+j+1;
    j = incept_char(p+i,str2);
    i=i+j+1;
    j = incept_char(p+i,str3);
    i=i+j+1;
    incept_char(p+i,str4);
    //将截取的字符串转成整型
    int num[4]={0};
    num[0] = atoi(str1);
    num[1] = atoi(str2);
    num[2] = atoi(str3);
    num[3] = atoi(str4);
    //组装成四字节无符号整型数,且为大端    
    unsigned int my_ip=0;
    printf("%ld\n",sizeof(my_ip));
    /***注意此处必须是unsigned char类型的指针,否则会打印出负数***/
    unsigned char *q = (unsigned char *)&my_ip;
    if(!is_big()){
        for(int m=0;m<4;m++){
            *(q+m)= *(char*)(num+m);
        }
    }else{//小端:地址低位存储数据低位
        for(int m=0;m<4;m++){
            *(q+m)= *(char*)(num+3-m);
        }
    }
    
    q=(unsigned char *)&my_ip;
    printf("%s --> %d.%d.%d.%d\n", argv[1], q[0], q[1],q[2], q[3]);
    return 0;
}
	
//将点分十进制的字符串 转换成  网络字节序的 无符号四字节整型
in_addr_t inet_addr(const char *cp);
//将网络字节序的无符号四字节整型的ip地址 转换成 点分十进制的字符串
char *inet_ntoa(struct in_addr in);
4. 端口号
端口号是用来人为的标识某一个进程
端口号范围[0-65535],usigned short
 实际开发时,端口由用户指定
linux系统中 /etc/services 中保存的就是当前系统中已经被占用的端口号
| 服务 | 端口号 | 
|---|---|
| ftp | 21 | 
| ssh | 22 | 
| tftp | 69 | 
| http | 80 8080 | 
| mysql | 3306 | 
(四)虚拟机的NAT模式和桥接模式
桥接模式:
NAT模式:



















