一.协议
1.1什么是协议
从应用的角度出发,协议可理解为“规则”,是数据传输和数据的解释的规则。
假设,A、B双方欲传输文件。规定:
第一次,传输文件名,接收方接收到文件名,应答OK给传输方;第二次,发送文件的尺寸,接收方接牧到该数据再次应答一个OK;
第三次.传输文件内容。同样.接收方接收数据完成后应答OK表示文件内容接收成功。,
由此,无论A、B之间传递何种文,都是通过三次数据传输来完成。A、B之间形成了一个最简单的数据传输规则。双方都按此规则发送、接收数据。A、B之间达成的这个相互遵守的规则即为协议。
这种仅在A、B之间被遵守的协议称之为原始协议。当此协议被更多的人采用,不断的增加、改进、维护、完善。最终形成一个稳定的、完整的文件传输协议,被广泛应用于各种文件传输过程中。该协议就成为一个标准协议。最早的 ftp协议就是由此衍生而来。·
TCP 协议注重数据的传输。http协议着重于数据的解释。
1.2典型协议
传输层:常见协议有 TCP/UDP协议。
应用层:常见的协议有HTTP协议,FTP协议。
网络层:常见协议有IP协议、ICMP协议、IGMP协议。网络接口层:RARP协议,以太网帧协议。
1.3分层模型结构
OSI七层模型:
物理层,数据链路层,网络层,传输层,会话层,表示层,应用层
TCP/IP四层模型:
网络接口层,网络层,传输层,应用层
通信过程:
数据在封装之前不能传输
应用层需要封装,传输层,网络层,链路层系统内核自己封装
以太网帧协议:
ARP协议:根据IP地址获取MAC地址,ARP广播
二.网络套接字函数
2.1IP地址转换函数
将字符串转化为数值型,或数值型转化为字符型
#include <arpa/inet.h>
int inet_pton(int af,const char *src, void *dst);
const char *inet_ntop.(int af,const void *src,char *dst,socklen_t size);
int inet_pton(int af,const char *src,void *dst) :
af: AF_INET、AF_INET6
src:传入,IP地址(点分十进制)
dst:传出,转换后的网络字节序的IP地址。192.168.1.10l
返回值:
成功:1
异常:0,说明src指向的不是一个有效的ip地址。
const char *inet_ntop(int af,const void *src,char *dst,sock1en_t size);
网络字节序--->本地字节序(string IP)
af:AF_INET、AF_INET6
src:网络字节序IP地址
dst。本地字节序(string IP)size:dst 的大小。
返回值:成功: dsto
失败:NULL
2.2大小端转换函数
计算机采用小端法,网络存储采用大端法。
uint32_t htonl(uint32_t hostlong); // 本地转网络
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
/*
h表示host,n表示network,l表示32位长整数,s表示16位短整数。
如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。
*/
2.3strcut sockaddr结构
struct sockaddr_in {sa_family_t sin_family; /* AF_INET */in_port_t sin_port; /* 端口号*/struct in_addr sin_addr; /* IP地址结构体, */};/* Internet address. */struct in_addr {uint32_t s_addr; /* IP地址,数值类型 */};
adir. sin_addr. s_addr = hton1 (INADDR_ANY);
取出系统中有效的任意IP地址,转为大端存储。二进制类型。
2.4socket模型创建流程图
服务器端有两个文件描述符,一个建立连接后被解放后,开始进行监听,另一个进行通信
2.5socket函数
socket:创建一个套接字
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>int socket(int domain, int type, int protocol);
domain:AF_INET , AF_INET6 , AF_UNIX
type:SOCK_STREAM (TCP), SOCK_DGRAM(UDP)
protocol: 0 自动匹配合适协议
成功:返回新套接字所对应的文件描述符
失败:-1 errno
2.6bind函数
bind:给socket绑定IP+端口号
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd:socket 函数返回值
addr:strcut sockaddr结构
struct sockaaar_in aaar ;
addr.sin_fami1y = AF_INET;addr. sin_port = htons(8888);
addr.sin_addr.s_addr = hton1(INADDR_ANY );addrlen:sizeof(addr)地址结构的大小
成功:0
失败:-1 error
2.7listen函数
listen:设置同时与服务器建立连接的上限数。(同时进行三次握手的客户端数量)
int listen(int sockfd, int backlog);
sockfd:socket 函数返回值
backlog:上限数值,最大值 128
成功 :0
失败:-1 errno
2.8accept函数
accept:阻塞等待客户端建立连接,成功的话返回一个与客户端成功连接的socket文件描述符
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd:socket 函数返回值
addr:传输参数,传输成功与服务器建立连接的那个客户端的地址结构(IP+端口号)
addrlen:传入传出,入:addr的大小。出:客户端addr的实际大小;
返回值:
成功:能与服务器进行通信的 socket 对应的文件描述符
失败:-1 error
2.9connect函数
connect:使用现有的socket与服务器建立连接
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:socket 函数返回值
addr:传入参数。地址结构(服务器的地址结构)
addlen:addr长度
成功:0
失败:-1 errno
如果不使用bind绑定客户端地址结构,采用"隐式绑定"
三.TCP协议
3.1TCP通讯时序
三次握手:
主动发起连接请求端,发送SYN标志位,请求建立连接。携带序号号、数据字节数(0)、滑动窗口大小。
被动接受连接请求端,发送 ACK 标志位,同时携带 SYN 请求标志位。携带序号、确认序号、数据字节数(O)、滑动窗口大小。主动发起连接请求端,发送ACK标志位,应答服务器连接请求。携带确认序号。
四次挥手:
主动关闭连接请求端,发送FIN标志位。被动关闭连接请求端,应答ACK标志位。
-----半关闭完成。
被动关闭连接请求端,发送FIN标志位。
主动关闭连接请求端,应答ACK标志位。
-----连接全部关闭