协议:
一组规则。
分层模型结构:
OSI七层模型:物,数,网,传,会,表,应
TCP/IP 4层模型:网(链路层/网络接口层),网(网络层),传,应
应用层:http,ftp,nfs,ssh,telnet
传输层:TCP
网络层:IP,ICMP,IGMP
链路层:以太网帧协议,ARP
网络传输流程:
数据没有封装之前,是不能在网络中传递的
以太网帧协议:
ARP协议:根据IP地址获取mac地址
以太网帧协议:根据mac地址,完成数据包传输
IP协议:
版本:IPV4 IPV6 —4位
TTL:time to live 。。 设置数据包在路由节点的跳转上限
该值减1,减为0的路由,有义务将该数据包丢弃
源IP:32位 192.168.1.108 —点分十进制 IP地址(String) —(二进制)
目的IP:32位
c/s模型:
client-server (客户端-服务器模型)
优点:缓存大量数据,协议选择灵活(可以自定义协议)
缺点:安全性,开发工作量大
b/s模型:
browser-server(浏览器-服务器模型)
缺点:不能缓存大量数据,严格遵守http协议
优点:安全,跨平台,开发工作量小(不用开发浏览器,只用搞服务器)
IP地址:可以在网络环境中,唯一标识一台主机
端口号(也就是PID进程ID):可以在网络的一台主机上,唯一标识一个进程
IP地址+ 端口号:可以在网络环境中,唯一标识一个进程
UDP:
16位:源端口号
16位:目的端口号
IP协议:
16位:源端口号
16位:目的端口号
32位序号
32位确认序号
6个标志位
16位窗口大小
网络套接字:socket(插板)
一个描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现)
在通信过程中,套接字肯定是成对出现的
intel一般都是小端法(pc存储)
TCP/IP协议,网络数据流应采用大端字节序(网络存储)
htonl函数 (提示:l代表long 四字节) host—>ntework 32位 (IP)
htons函数 本地—>网络 (提示 s代表short,2字节) (port)
ntohl 函数 网络—>本地(IP)
ntohl 函数 网络—>本地(port)
192.168.1.11—->string—->atoi—>int—>htonl—->网络字节序
IP地址转换函数
int inet_pton(int af,const char * src,void *dst) 本地字节序(String)—->网络字节序
(IP协议)af:AF_INET(IPV4) AF_INET6(IPV6)
src:传入:IP地址(点分十进制)
dst:传出:转换后的网络字节序的IP地址
返回值:
成功:1
异常:0,说明src指向的不是一个有效的IP地址
失败:-1
const char* inet_ntop(int af,const char * src,char *dst,socklen_t size);
(IP协议)af:AF_INET(IPV4) AF_INET6(IPV6)
src:网络字节序IP地址
dst:本地字节序(String IP)
size:dst 的大小
返回值:
成功 :dst
失败: NULL
sockaddr地址结构:
struct sockaddr_in addr:
addr.sin_family=AF_INET/AF_INET6 (如何查看addr成员 man 7 ip)
addr.sin_port=htons(9527);
addr.sin_addr.s_addr=inet_pton(AF_INET,“192.157.22.6”,dst)
分两步:
int dst;
inet_pton(AF_INET,“192.157.22.6”,(void *)&dst)
addr.sin_addr.s_addr=dst;
(*)addr.sin_addr.s_addr=htonl(INADDR_ANY) (取出系统中有效的任意的IP地址,二进制类型)
记得添加头文件#include<arpa/inet.h>
bind(fd,(struct sockaddr *)&addr,size);
socket函数
#include<sys/socket.h>
int socket (int domain,int type,int protocol);
domain:AF_INET AF_INET6 AF_UNIX
type:SOCK_STREAM SOCK_DGREM
protocol:0
返回值:成功:新套接字对应文件描述符
失败:-1 error
int bind(int sockfd,const struct sockaddr * addr,socklen_t addrlen)
给socket绑定一个地址结构(IP +port)
sockfd:socket 函数返回值
struct sockaddr_in addr:
add.sin_family=AF_INET;(这个参数应该和socket 中的domain保持一致)
addr.sin_port=htons(8888)
addr.sin_addr.s_addr=htonl(INADDR_ANY);
addr:(struct sockaddr *)&addr
addlen:sizeof(addr)地址结构大小
返回值:
成功:0
失败:-1 error
int listen(int socket, int backlog);
设置同时与服务器建立连接的上限数(同时进行3次握手的客户端数量)
sockfd:socket 函数返回值
backlog:上线数量,最大值128
返回值:
成功:0
失败:-1 error
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
阻塞等待客户端建立连接,成功的话,返回一个与客户端成功连接的socket文件描述符。
sockfd:socket 函数返回值
addr:传出参数。成功与服务器建立连接的那个客户端的地址结构(IP+port)
(与bind第二个参数相差一个const,所以就大不相同)
socklen_t clit_addr_len=sizeof(addr)
addrlen:传入传出。&clit_addr_len
入:addr大小。出:客户端addr实际大小
返回值:
成功:能与服务器进行数据通信的socket对应的文件描述符
失败:-1 error
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
使用现有的socket与服务器建立连接
sockfd:socket返回值
struct sockaddr_in srv_addr; //服务器地址结构
srv_addr.sin_port=9527 跟服务器bind时设定的port完全一致
inet_pton(AF_INET,“服务器IP地址”,&srv_addr.sin_addr.s_addr);
addr:传入参数。服务器的地址结构
addlen:服务器地址结构的大小(长度)
返回值:
成功:0
失败:-1 error
如果不适用bind绑定客户端地址结构,采用“隐式绑定”,