七层网络模型:
为了数据完整,安全地在网络中传递,ISO将数据的传递从逻辑上划分以下七层;
1.应用层:主要用于将数据交给应用程序
2.表示层:主要用于按照统一的格式进行数据封装等;
3.会话层:主要用于控制对话的建立,关闭等操作;
4.传输层:主要用于数据的检查和重新排序;
5.网络层:主要用于选择具体网络协议再次封装和发送等;
6.数据链路层:主要用于将数据转换成高低电平信号等;
7.物理层:主要指交换机等网络设备;
常用的网络协议:
1.tcp协议 传输控制协议,是一种面向链接的协议,类似打电话
2.udp协议 用户数据报协议,是一种非面向对象链接协议,类似写信
3.ip协议 互联网协议,是上述两种协议的底层协议
***IP地址和子网掩码***
1>IP地址:互联网中唯一地址标识,其本质上就是一个由32位二进制组成的整数(ipv4);
也有128位二进制组成的整数(ipv6)
日常生活中采用点分十进制表示法来描述IP地址;
也就是将每一个字节的二进制转换成一个十进制的整数,不同的整数之间采用小数点分隔;
为里便于IP地址的管理,将IP地址分为网络地址和主机地址两部分;
根据IP地址中网络地址和主机地址的位数不同分为四类:
A类:0 + 7为网络地址 + 24位主机地址
B类:10 + 14位网络地址 + 16位主机地址
C类:110 + 21位网络地址 + 8位主机地址
D类:1110 + 28位多播地址
查看ip地址的指令:ifconfig /sbin/ifconfig
子网掩码:
主要用于划分IP地址中的网络地址和主机地址,以判断两个IP地址是否在同一个子网中;
具体划分如下:
IP地址 & 子网掩码 = 网络地址 + 主机地址
端口号和字节序
IP地址:定位到具体的某一台主机/设备
端口号:定位到主机上的具体某个进程;网络编程中需要提供:IP地址 + 端口号
端口号本质上是unsigned short类型;范围 0 ~ 65535,其中0 ~ 1024被系统占用;
因此编程从1025开始使用
字节序:
低端系统:主要指将低位数据存放在低位内存地址的系统
高端系统:主要指将低位数据存放在高位内存地址的系统
比如:0x12345678
低端系统存放:0x78 0x56 0x34 0x12
高端系统存放:0x12 0x34 0x56 0x78
一般性原则:
一般来说,对于所有发送到网络中的多字节整数来说,先转换为网络字节序再发送;
而对于所有从网络中接受过来的多字节整数来说,需要先转换为主机字节序再解析,
而网络字节序本质上就是大端系统的字节序;
***基于sockt一对一通讯模型***
通信模型
主机A:
1.创建sockt,使用sockt函数;
2.准备通信地址,使用结构体类型;
3.绑定socket和通信地址,使用bind函数;
4.进行通讯,使用read/write函数;
5.关闭sockt,使用close函数;
主机B:
1.创建sockt,使用sockt函数;
2.准备通信地址,使用主机A的地址;
3.绑定socket和通信地址,使用connect函数;
4.进行通讯,使用read/write函数;
5.关闭sockt,使用close函数;
****************************************************
socket相关函数解析:
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
第一个参数:决定了本地通讯还是网络通信
AF_LOCAL/AF_UNIX: 表示实现本地通讯
AF_INET: 表示实现基于ipv4的网络通讯
AF_INET6: 表示实现基于ipv6的网络通讯
第二个参数:具体的通讯类型;决定了具体的通讯协议
SOCK_STREAM:基于tcp协议的通讯方式
SOCK_DGRAM: 基于udp协议的通讯方式
SOCK_RAW: 基于ip协议的通讯方式
第三个参数:具体的特殊协议;通常不使用,赋值0即可
返回值:成功返回文件描述符;失败返回-1;
函数功能:主要用于创建用于交流/通信的端点;
***通信地址的常用数据类型***
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
该数据类型主要用于函数的形参,基本不会定义结构体变量去使用;
#include <sys/un.h>
struct sockaddr_un{
sa_family_t sun_family; 协议族,和socket函数的第一个参数保持一致即可;
char sun_path[]; socket文件的路径名称;
};
主要用于实现本地通信;
#include <netinet/in.h>
struct sockaddr_in{
sa_family_t sin_family; 协议族,AF——INET
int_port_t sin_port; 端口号
struct in_addr sin_addr; ip地址
};
struct in_addr{
int_addr_t s_addr; 整数类型的ip地址
};
主要用于网络通讯;
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
第一个参数:socket文件描述符;
第二个参数:结构体指针,用于指定通信地址,需要进行类型转换
第三个参数:通讯地址的大小,使用sizeof计算
函数功能:主要用于socket和指定通信地址;
返回值:成功返回0;失败返回-1;
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
函数功能:
主要用于建立socket到通信地址的连接,参数和返回值参考bind函数即可;
******字节序转换函数******
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
将主机字节序转换成网络字节序
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
将网络字节序转换成主机字节序
******ip地址转换函数******
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t inet_addr(const char *cp);
将字符串ip地址转换成int类型的ip地址
char *inet_ntoa(struct in_addr in);
将结构体类型的ip地址转换为字符串类型的ip地址
******tcp协议的网络通信******
通信模型:
1.服务器:servers
1.创建socket,使用socket函数
2.准备通讯地址,使用结构体函数;
3.绑定socket和通讯地址,使用bind函数;
4.监听,使用listen函数;
5.响应客户端的链接请求,使用accept函数;
6.进行通讯,使用send/recv函数;
7.关闭socket,使用close函数;
2.客户端:client
1.创建socket,使用socket函数;
2.准备通信地址,使用服务器的地址;
3.链接socket和通讯地址,使用connect函数;
4.进行通信,使用send/recv函数;
5.关闭socket,使用close函数;
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd, int backlog);
第一个参数:socket描述符;
第二个参数:指定悬而未决链接请求队列的最大长度,该队列为满时,
有客户端发来链接请求,则会被拒绝;
函数功能:主要用于将参数sockfd指定的socket标记为被动的socket;
也就是原来的socket是可以用于通信的,但是标记为被动的socket之后,
专门用来响应即将到来的链接请求,不再用于通信;
返回值:成功返回0;失败返回-1;
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
第一个参数:socket描述符;
第二个参数:结构体指针,用于带出客户端的通讯地址;
第三个参数:结构体指针,用于带出通讯地址的大小;
函数功能:
主要用于响应指定socket上面的一个链接请求;
该函数会提取悬而未决链接请求队列中的第一个链接请求响应,响应的方式就是再创建一个链接好的socket进行通信;
返回值:成功返回可以通信的socket的描述符;失败返回-1;
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd,const void *buf,size_t len,int flags/*0*/);
返回值:成功返回发送数据的大小;失败返回-1;
函数功能:主要用于向指定的socket发送数据内容;
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags/*0*/);
返回值:成功返回实际接收数据的大小;失败返回-1;
函数功能:主要用于接收指定的socket中的数据;
******************TCP和UDP协议的比较**********************
1.tcp协议的基本概念和特性
tcp:传输控制协议,是一种面向链接的协议;
建立链接===>进行通讯===>断开链接
在通讯的整个过程中全程保持链接;
保证了数据传输的可靠性和有效性;
数据的接收方会实时通知数据的发送方可以接收的数据大小,
以避免发送方发送数据过多而带来的溢出问题;
是一种全双工的字节流通信方式;
2.udp协议的基本概念和特性
udp:用户数据报协议,一种非面向链接协议;
在通信的整个过程中不许要全程保持链接;
不保证数据传输的可靠性和有序性;
是一种全双工的数据报通信方式;
发送数据的效率比较高;
******************TCP和UDP协议的比较**********************
基于udp协议的网络通信模型
1.通信模型:
服务器:
1.创建socket,使用socket函数
2.准备通信地址,使用结构体类型;
3.绑定socket和通信地址,使用bind函数;
4.进行通信,使用send/sendto/recv/recvfrom函数;
5.关闭socket,使用close函数;
客户端:
1.创建socket,使用socket函数;
2.准备通信地址,使用服务器的地址;
3.进行通信,使用send/sendto/recv/recvfrom函数;
4.关闭socket,使用close函数;
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
第五个参数:指定收件人通信地址;
第六个参数:指定收件人通信地址大小;
返回值:成功返回发送内容的大小;失败返回-1;
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
第五个参数:指定发件人通信地址;
第六个参数:指定发件人通信地址大小;
返回值:成功返回接收内容的大小;失败返回-1;