一、什么网络通信
计算机网络把分布在不同地理区域的计算机与专门的外部设备用通信线路互联成一个规模大、功能强的网络系统,从而使众多的计算机可以方便的互相传递信息、共享硬件、软件、数据信息等资源。网络编程直接或间接地通过网络协议与其它计算机实现数据交换,进行通信。
OSI参考模型 | TCP/IP参考模型 | TCP/IP参考模型各层对应协议 |
---|---|---|
应用层 | 应用层 | HTTP、FTP、Telnet、DNS…… |
表示层 | ||
会话层 | ||
传输层 | 传输层 | TCP、UDP…… |
网络层 | 网络层 | IP、ICMP、ARP…… |
数据链路层 | 物理+数据链路层 | Link |
物理层 |
二、IP和端口号
在通信时,通信双方必须知道对方的标识。互联网上每个计算机的唯一标识就是 IP 地址。IP 地址实际上就是一个 32 位整数(IPv4),它是以字符串表示的 IP 地址。
IP 协议负责把整个数据从一台计算机通过网络发送到另一台计算机。数据被分割成一小块一小块,然后通过 IP 包发送出去。由于互联网链路复杂,两台计算机之间经常有多条线路,因此,路由器就负责决定如何把一个 IP 包转发出去。IP 包的特点就是按快发送,途径多个路由,但不保证都能到达,也不能保证顺序到达。
- IP地址:InetAddress
- 唯一的标识 Internet 上的计算机(通信实体)
- 本地回环地址(hosAddress):127.0.0.1 主机名(hostName):localLost
- IP地址分类方式1:IPV4 和 IPV6
- IPV4:4个字节组成,大概42亿,其中 30 亿大概在北美,亚洲 4 亿。2011 年已经用尽。以点分十进制表示
- IPV6:128位(16个字节),写成 8 个无符号整数,每个整数用四个十六进制位标识,数之间用冒号分开
- IP地址分类方式2:公网地址(万维网使用)和 私有地址(局域网使用)
- 192.168. 开头的就是 私有地址,范围即为 192.168.0.0 ~ 192.168.255.255,专门为组织机构内部使用
- 端口号:标识正在计算机上运行的进程(程序)
- 不同的进程有不同的端口号
- 被规定为 16 位的整数 0~65535
- 端口分类:
- 公认端口:0~1023。被预先定义的服务通信占用
- 注册端口:1024~49151。分配给用户进程或应用程序
- 动态/私有端口:49152~65535
- 端口号与 IP 地址的组合得出一个网络套接字:Socket
三、Socket套接字
为了让两个程序通过网络进行通信,二者均必须使用 Socket 套接字。Socket 的英文原义是 “孔” 或 “插座”,通常也称作为 “套接字”,它用于描述 IP 地址和端口号,它是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在 Internet 上的主机上一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个 Socket,并绑定到一个端口上,不同的端口对应于不同的服务。
在 Python 中使用 socket 模块的 socket() 函数进行网路套接字编程。
socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
函数 socket.socket() 创建一个 socket,它返回该 socket 的描述符,参数说明如下:
- family: 可以选择 AF_INET(用于 Internet 进程间通信)或者 AF_UNIX(用于同一机器进程间通信);
- type: 套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)
创建完成后,生成一个 socket 对象,socket 对象的主要属性和方法如下:
【1】、数据属性
socket.family # 套接字家族
socket.type # 套接字类型
socket.proto # 套接字协议
【2】、服务器套接字方法
socket.bind(address) # 将地址(主机名、端口号对)绑定到套接字上
socket.listen([backlog]) # 设置并启动TCP监听器
socket.accept() # 被动接收TCP客户端连接,一直等待直到连接到达(阻塞)
【3】、客户端套接字方法
socket.connect(address) # 主动发起TCP服务器连接
socket.connect_ex(address) # connect的扩展版本,此时会以错误码形式返回问题,而不是抛出一个异常
【4】、普通的套接字方法
socket.recv(bufsize[, flags]) # 接收TCP消息
socket.recv_into(buffer[, nbytes[, flags]]) # 接收TCP消息到指定的缓冲区
socket.send(bytes[, flags]) # 发送TCP消息
socket.sendall(bytes[, flags]) # 完整的发送TCP消息
socket.recvfrom(bufsize[, flags]) # 接收UDP消息
socket.recv_into(buffer[, nbytes[, flags]]) # 接收的UDP消息到指定的缓冲区
socket.sendto(bytes[, flags], address) # 发送UDP消息
socket.getpeername() # 连接到套接字(TCP)的远程地址
socket.getsockname() # 当前套接字地址
socket.getsockopt(level, optname[, buflen]) # 返回给定套接字选项的值
socket.setsockopt(level, optname, value) # 设置给定套接字选项的值
socket.shutdown(how) # 关闭连接
socket.close(fd) # 关闭套接字
socket.detach() # 在未关闭文件描述符的情况下关闭套接字,返回文件描述符
socket.ioctl(control, option) # 控制套接字模式(仅支持Windows)
【5】、面向阻塞的套接字方法
socket.setblocking(flag) # 设置套接字的阻塞或者非阻塞模式
socket.settimeout(value) # 设置阻塞套接字操作的超时时间
socket.gettimeout() # 获取阻塞套接字操作的超时时间
【6】、面向文件的套接字方法
socket.fileno() # 套接字的文件描述符
socket.makefile(mode='r', buffering=None, *, encoding=None, errors=None, newline=None) # 创建与套接字关联的文件对象
四、网络协议
计算机网络中实现通信必须有一些规定,即通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等指定标准。在指定协议时,把复杂成份分解成一些简单的份,在将它们复合起来。最常用的复合方式是层次方式,即 同层间可以通信、上一层可以调用下一层,而与下一层不发生关系。各层互不影响,利于系统的开发和扩展。
- 传输层协议中有两个重要的协议:
- 传输控制协议 TCP(Transmission Control Protocol)
- 使用 TCP 协议前,须建立 TCP 连接,形成传输数据通道
- 传输前,采用“三次握手”的方式,点对点通信、是可靠的
- TCP 协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
- 用户数据报协议 UDP(User Datagram Protocol)
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据包的大小限制在 64K 内
- 发送不断对方是否准备好,接收方收到也不确认,故是不可靠的
- 可以广播发送
- 发送数据结束时无需释放资源,开销小,速度快
- 传输控制协议 TCP(Transmission Control Protocol)
- 网络互联协议 IP(Internet Protocol)是网络层的组要协议,支持网间互联的数据通信
- TCP/IP 协议模型从更使用的角度出发,形成了高效的四层体系结构,即 物理链路层、IP层、传输层 和 控制层;