01_socket套接字
是一个能够在多个系统(x86、unix、Linux)下运行的一组API接口,不仅仅只能跑tcp/ip协议,既可以网络通信,也可以IPC通信(计算机内部通信)。
01_01套接字类型
1.流式套接字(SOCK_STREAM):提供了一个面向连接、可靠的数据传输服务,
数据无差错、无重复的发送且按发送顺序接受。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。针对TCP
2.数据报套接字(SOCK_DGRAM)
提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错服务保证,数据可能丢失或重复,顺序发送,可能乱序接受。针对UDP
3.原始套接字(SOCK_RAW)可以对较低层次协议如IP、ICMP直接访问。(ping、traceroute使用该协议)
01_02socket网络编程在网络协议的位置
01_02_01 OSI理想化模型分层
OSI 7 层模型(理想化模型): 物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
01_02_02 TCP/IP模型
tcp/ip4层模型:
1)应用层 常见的协议有HTTP协议,FTP协议。
2)传输层 常见协议有TCP/UDP协议。
3)网络层 常见协议有IP协议、ICMP协议、IGMP协议。
4)网络接口物理层 常见协议有ARP协议、RARP协议。
注:
HTTP超文本传输协议(Hyper Text Transfer Protocol)是互联网上应用最为广泛的一种网络协议。
FTP文件传输协议(File Transfer Protocol)
IP协议是因特网互联协议(Internet Protocol)
TCP传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
UDP用户数据报协议(User Datagram Protocol)是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
ICMP协议是Internet控制报文协议(Internet Control Message Protocol)它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。
IGMP协议是 Internet 组管理协议(Internet Group Management Protocol),是因特网协议家族中的一个组播协议。该协议运行在主机和组播路由器之间。
ARP协议是正向地址解析协议(Address Resolution Protocol),通过已知的IP,寻找对应主机的MAC地址。
RARP是反向地址转换协议,通过MAC地址确定IP地址。
在tcp/ip中socket的位置:是传输层和应用层中的一个抽象层API接口
02_TCP服务器端流程
02_01什么是服务器
我们使用应用程序有两种模型。b/s模型(Browser/Server) c/s模型(client/server)
C/S :传统的网络应用设计模式,客户机(client)/服务器(server)模式。需要在通讯两端各自部署客户机和服务器来完成数据通信。
B/S :浏览器(Browser)/服务器(server)模式。只需在一端部署服务器,而另外一端使用每台PC都默认配置的浏览器即可完成数据的传输。
选用C/S模型的优点: 1. 协议选用灵活。 (可以在标准协议的基础上根据需求裁剪及定制。例如,腾讯公司所采用的通信协议,即为ftp协议的修改剪裁版。)
02_02 API函数
流程中的API函数全部是系统调用,即是操作系统(Linux内核)中的,无需程序员自己去写。下面逐个介绍。
socket() 创建套接字
bind() 绑定本机地址和端口
connect() 建立连接
listen() 设置监听套接字上限
accept() 接受TCP连接
recv(), read(), recvfrom() 数据接收
send(), write(), sendto() 数据发送
close(), shutdown() 关闭套接字
1.socket
int socket(int domain, int type, int protocol);
domain参数一:
AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址
AF_INET6 与上面类似,不过是来用IPv6的地址
AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用
type参数二,01_01已经介绍套接字的类型:
SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
SOCK_RAW socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
protocol参数三:
传0 表示使用默认协议。返回值:
成功:返回指向新创建的socket的文件描述符,失败:返回-1,设置errno
2.bind
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd参数一:
socket文件描述符
addr参数二:
构造出IP地址加端口号
addrlen参数三:
sizeof(addr)长度返回值:
成功返回0,失败返回-1, 设置errno
注意:参数二是结构体类型,成员变量有IP和PORT,参数二传入初始化后的指针,例如:
struct sockaddr_in servaddr;
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6666);其中地址类型为AF_INET,网络地址为INADDR_ANY,这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP地址,端口号为6666。参数二传入&servaddr即可。
3.listen
int listen(int sockfd, int backlog);
sockfd:
socket文件描述符
backlog:
要监听的套接字的上限返回值:成功返回0,失败返回-1。
有许多客户端要连接,因accept一次循环处理一个客户端,其他客户端是待连接状态,listen设置待连接状态的客户端数量,收到更多的连接请求就忽略。
4.accept
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockdf:
socket文件描述符
addr:
传出参数,返回链接客户端地址信息,含IP地址和端口号
addrlen:
传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小返回值:
成功返回一个新的socket文件描述符,用于和客户端通信,失败返回-1,设置errno
accept函数整个是一个while死循环,每次循环处理一个客户端连接。
5.connect
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockdf:
socket文件描述符
addr:
传入参数,指定服务器端地址信息,含IP地址和端口号
addrlen:
传入参数,传入sizeof(addr)大小
返回值:
成功返回0,失败返回-1,设置errno
02_03c/s服务器和客户端搭建流程
c/s 服务器搭建流程:
创建套接字 :socket
绑定ip和端口 :bind
建立监听 :listen
接收/处理客户端连接请求 :accept
正常通信
read/recvfrom/recv
write/sendto/send
通信完毕,关闭套接字
c/s客户端搭建流程:
创建套接字:socket
绑定:bind<可选>,默认隐式绑定
主动连接服务器:connect
正常通信
read/recvfrom/recv
write/sendto/send
通信完毕,关闭套接字
03_ 以太网头、ip头、tcp头
03_01以太网头
以太网是网络接口物理层的,MAC地址是网卡,即48位全球唯一,网络设备的身份标识
以太网包头(MAC Header)前6个字节是目的MAC地址,接着六个字节是源MAC地址,后两个字节是网卡类型:0x08C0 IPV4,0x86DD IPV6,0x08C6 ARP(正向地址解析协议,由IP地址找到MAC地址),0x80f3(反向地址解析协议,由MAC地址找到IP)
发送
03_02ip头
ip地址占4个字节
12-15字节:源ip地址
16-19字节:目的ip地址
4-5字节,5-5.75,5.75-7字节先不管
0-0.5字节:IP版本——IPv4/IPv6
0.5-1字节: 头部长度——20字节/24字节
1字节:服务类型,贵的会好一些,这里忽略
2-3字节:总长度:最多2的16次方——16KB
8字节:生命周期,超时则丢包
9字节: 下一层的传输层协议是UDP或TCP
10-11字节: CRC校验16位
03_03tcp头
0-1字节:源端口
2-3字节:目的端口
4-7字节:序列号
8-11字节:确认序列号
12-12.5字节:tcp头到data之间的偏移
12.5-13字节:预留
13字节:TCP标志
14-15字节:数据窗
16-17字节:16位CRC校验位
18-19字节:紧急指针(OOB)
20-24字节:TCP可选项
IP协议和TCP协议都有差错处理(含有CRC检验),但是第三层的IP协议和第四层的以太网协议都是不可靠的。TCP协议是可靠的,TCP把所有要发送的数据进行编号〈每一个字节用一个号),而且它有确认和重发机制:
发送数据包时,假设有100K数据要发,每个包有1k即1024个字节,数据窗就是1023(发送时从当前数据位置,发送window大小的数据),序列号SYN=1023,如果接收端收到数据,标志位就变为A 0x10 Ack,确认序列号ACK变为1024:这代表了①前面1023个字节都收到②请从1024号开始分配。这里确认序列号和序列号之间进行了确认,如果对不上,就重新发送,这就是确认和重发机制。
03_04TCP/IP协议网络封包和拆包
封包格式:
一次性最多只能发送1500字节个数据(1k多一点),那么传送100k的数据如果一个包1k就需要来连续的100个TCP包,
拆包如下,跟tcp头有关:
上面ip头、4-23字节用于拆包
4-5字节:设置每个包的id
5-5.75字节:0x40 D没有碎片化,0x20 M更多碎片化。如果后面还有包,设置M=1,如果是 最后一个包设置D=1
5.75-7字节:每个包当前的偏移,第二个开头应该是1024(写成1000了)
03_05TCP协议优势
TCP是一种面向连接的,可靠的数据传输
①TCP的可靠传输:通过确认和重发机制
1.TCP把所有要发送的数据进行编号〈每一个字节用一个号)
2.发送时从当前数据位置,发送window大小的数据
②TCP是面向连接的:TCP三次握手,四次挥手
过程就像互相发一次数然后确认,客户端向服务器发送SYN=j序列号,服务器端回应ACK=j+1,和序列号SYN=k ,客户端回应ACK=k+1
这里四次挥手区分 一个字节的标志位ACK和FIN,和四个字节的序列号和确认序列号seq,ack
因为有time_wait(30s-2min),断开连接后不能马上连接,需要在服务器端设置地址快速重用
int b_reuse = 1;
setsockopt (fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof (int)) ;