OSI七层模型和TCP/IP四层模型
通信时需要用到网络模型来进行数据封装。一层一层封装和拆包。
OSI 模型把网络通信的工作分为 7 层,从下到上分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
分层太多,增加了网络工作的复杂性。 简化为4 层TCP/IP 模型。
程序发送数据的流程
程序要发送数据如下:
1.数据传递给TCP协议层(传输层)
2.TCP协议将数据分段并标识序列号,记录数据段发送时间和状态,便于数据重传和确认。
3. IP协议封装TCP协议传递过来的数据段,在数据包的头部添加源地址、目的地址等信息。同时,IP协议会通过路由算法选择合适路径发送数据包到目的地址。
IP地址,DNS,MAC地址,端口号
IP地址:标识位置。在网络上通信时,必须要知道对方的 IP 地址。根据IP找到对方地理位置。
DNS:域名和IP的映射。因为ip是一大串可能记不住,所以可以输入域名,通过DNS找到ip,从而访问想要的地址。
MAC地址:标识电脑。计算机出厂时,MAC 地址已经被写死到网卡。局域网中的路由器/交换机会记录每台计算机的 MAC 地址。
端口号:标识网络程序。例如,Web 服务的端口号是 80,FTP 服务的端口号是 21,SMTP 服务的端口号是 25。
网络通信的数据包中会有 IP 地址、 MAC 地址、端口。(下面会具体讲解)
1.通过IP找到目标的地理位置
2.通过MAC找到具体是哪台计算机
3.通过端口找到是哪个进程。
套接字socket
应用程序通过一个Socket建立一个远程连接,Socket内部通过一个TCP/IP协议把数据传输到网络。
简单的通信流程:
- 服务器先启动,等待客户端主动连接。
- 三次握手建立连接。
- 客户端发送数据,服务器接收数据,处理该请求,发回一个响应。循环这个过程。
- 客户端关闭连接,服务器收到后也关闭对应的 Socket,然后结束运行或者等待新的客户连接。
int socket(int af, int type, int protocol);
af:地址族(adress family),IP地址类型。
AF_UNIX:同一机器进程间通信。AF_INET:IPV4协议的TCP和UDP。AF_INET6:IPV6协议的TCP和UDP。
type:套接字类型。
SOCK_STREAM:流式,TCP,面向连接。
SOCK_DGRAM:报文,UDP,无连接。
protocol:传输协议。一般不填,默认为0。
IPPROTO_TCP :TCP传输协议。
IPPTOTO_UDP:UDP 传输协议。
s = socket(AF_INET, SOCK_STREAM, 0);
服务器套接字函数:
s.bind(host,port):绑定地址到套接字
s.listen(n):开始TCP监听,n表示接受n个排队,所以最大连接数为:n+1
s.accept():阻塞式建立TCP连接,等待客户端请求
客户端套接字函数:
s.connect(host,port):建立TCP服务连接
s.connect((host,port)):同上,但是传入的是个元组,出错返回socket.error
s.connect_ex():出错返回错误码
公共的套接字函数:
s.recv(n):接收小于n字节的TCP数据,返回字符串。
s.send(str):发送字符串到套接字
s.sendall(str):发送完整数据,返回字符串长度(字节大小)
s.close():关闭套接字
UDP的套接字函数:
s.recvfrom():返回元组(data,adress)
s.sendto():发送的数据是元组(ipaddr,port)返回发送的字节数
缓冲区
每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。
先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送到目标机器,不会直接发送到网络。
一旦将数据写入到缓冲区,函数就可以成功返回,由TCP协议负责发送到网络。TCP何时发具体需要根据实际情况。例如网络情况、当前线程是否空闲等因素。
读的时候,也从输入缓冲区中读取数据,而不是直接从网络中读取。