此博客仅用于分享本人在求职路上的学习内容部以及过程(第四天)。
网络编程三要素
在Python中,要实现多台计算机实现网络通信,需要使用到网络编程的三要素:IP地址、端口号、协议。除了这三大要素之外,Socket套接字和编码的转换在Python网络编程中也是至关重要的。
IP地址
什么是IP地址
概念
:IP地址(Internet Protocol Address)是Internet协议栈中的重要概念,它是一个32位(4字节)的数字,用于唯一标识Internet中的计算机。
作用
:IP地址是Internet通信的基础,它被用于标识Internet中的计算机,并确定计算机之间的通信方式。
结构
:IP地址是由二进制数表示,但通常以人类可读的格式(如IPv4的点分十进制或IPv6的十六进制)呈现。
查看IP地址与检查网络连接
既然IP地址是用于唯一标识Internet中的计算机,那么如何获取IP地址和检查网络连接是否正常就是网络编程中常见的两个操作了。
我们可以通过键盘上的win + R
组合键打开窗口后输入cmd
,进入终端模式,然后输入ipconfig
查看IP地址。如图所示:
在cmd终端中,我们可以通过ping + IP地址
的形式检查是否能访问该IP地址。如:ping 127.0.0.1
(127.0.0.1是本地IP地址)。
端口
计算机通信原理
问题:如果在一台电脑上使用飞秋给另外一台电脑上的飞秋发送数据并且另外的这台电脑还运行着多个软件,它是如何区分这多个软件把数据给飞秋的呢?
答:其实,每运行一个程序都会有一个端口,想要给对应的程序发送数据,找到对应的端口即可。端口就是传输数据的通道,好比教室的门,是数据传输必经之路。
而且每一个端口都会有一个对应的端口号(操作系统为了统一管理这么多端口,就对端口进行了编号,这就是端口号,端口号其实就是一个数字,好比我们现实生活中的门牌号),想要找到端口通过端口号即可,如:飞秋软件的默认端口号就是2345。
最终通信结果:通过ip地址找到对应的设备,通过端口号找到对应的端口,然后通过端口把数据给应用程序。
端口号扩展
端口号根据其范围(0-65535) ,可以分为如下几类:
- 0-1023:是知名端口号,这些端口号一般固定分配给一些服务,比如21端口分配给FTP(文件传输协议)服务,22端口分配给SSH( 安全外壳协议,主要用于远程连接与文件传输),25端口分配给SMTP(简单邮件传输协议)服务,80端口分配给HTTP服务,443端口分配给HTTPS服务等等。
- 1024-65535:是给一般程序员开发应用程序使用端口号称为动态端口号。如果程序员开发的程序没有设置端口号,操作系统会在动态端口号这个范围内随机生成一个给开发的应用程序使用。
- 1024~49151:注册端口(需IANA注册)。
- 49152~65535:动态/私有端口(临时使用)。
协议
概念和常见的协议
概念
:协议是计算机网络中通信双方预先定义的规则和标准,用于规范数据的格式、传输方式、交互顺序和错误处理,确保不同设备或程序能够正确、可靠地交换信息。
常见的协议
:TCP/IP协议,UDP协议,HTTP协议,FTP协议,SMTP协议,POP3协议,IMAP协议,DNS协议等等。而在Python的网络编程中,我们要用到的协议的则是TCP协议和UDP协议。
TCP协议
概念
:TCP的英文全拼(Transmission Control Protocol)简称传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议。
特点
:
- TCP协议是面向连接的,即在发送数据之前,必须建立连接,然后才能发送数据。在接收数据之后,必须确认数据已接收,然后才能关闭连接。
- TCP协议是可靠的,即发送方发送数据之后,接收方必须确认数据已接收,否则发送方会重发数据。
- TCP协议是字节流,即发送方发送。
作用
:TCP协议用于实现可靠、有序的数据传输,适用于需要可靠、有序的数据传输场景,如文件传输、数据库传输、网络游戏等等。
UDP协议
既然TCP是可靠协议,那么UDP就是 unreliable protocol(不可靠协议)。因此我们在日常通信、数据传输一定要保证可靠性,所以一般使用TCP。然而TCP协议的最大接收数据速率为1024字节,不适合大数据的接收和传输。在如下几个方面则需要使用到UDP协议:
- 实时视频/音频流(Zoom、Twitch)。
- 在线游戏(王者荣耀、PUBG)。
- DNS查询。
- VoIP(如微信语音)。
- IoT设备通信(传感器数据)。
Socket套接字
概念
:Socket套接字是网络编程中的基础,它是计算机之间进行通信
的一种约定
或一种方式。通过socket这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。
通过生活案例来说:这就好比现实中的电话,当知道了对方的电话号码后需要使用电话才能进行通讯,程序之间想要进行网络通信需要基于这个socket套接字,socket套接字就是程序间进行网络通讯的工具。
编码转换
概念
:编码转换是计算机网络中一个重要的概念,它用于将数据从一种编码格式转换为另一种编码格式。编码转换的目的是为了方便计算机处理数据,将数据从原始的二进制数据转换为可读的文本数据。
在计算机网络中,数据都是以二进制的形式进行传输的。所以在网络传输数据的时候,数据需要先编码转化为二进制(bytes)数据类型。例:I Love Python => 字符串 => 转换为二进制数据 => 网络中传输。
编码转换的方法:
函数名 | 说明 |
---|---|
encode | 编码 将字符串转化为字节码 |
decode | 解码 将字节码转化为字符串 |
提示
:encoded()和decode()函数可以接受参数,encoding是指在编解码过程中使用的编码方案,一般默认为utf-8
。
TCP服务器端和客户端的开发实践
服务器端
服务器端的开发步骤大致可以分为如下七个步骤:
- 创建Socket对象。(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
- socket对象绑定自己连接信息(ip地址和端口号)。(bind()函数,只能接收
一个
元组) - 服务器端开始监听 (listen()函数,区间为1-128)
- 等待客户端的连接 (recv()函数,接收数据,返回一个元组,包含数据,和客户端的连接信息,且最大接收字节长度为1024字节)
- 接收客户端传输的数据 (接收到的数据是二进制数据,需解码为字符串)
- 向客户端发送数据 (send()函数,发送数据,参数为字符串,会自动编码为二进制数据)
- 释放内存 (close()函数,关闭Socket对象)
下面代码将演示完整的服务器端开发步骤:
import socket
# 当前代码为服务端代码
# 1、创建服务器端Socket
serve_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2、绑定IP和端口号
# 127.0.0.1表示本机ip地址,12344表示端口号
serve_socket.bind(("127.0.0.1", 12344))
# 3、设置最大监听数(设置5,区间;1 - 128)
serve_socket.listen(30)
print("服务器启动成功")
# 4、具体的监听动作,接收客户端请求,并获取一个Socket对象,负责和客户端进行交互
client_socket, client_addr = serve_socket.accept()
while True:
# # 5、给客户端发送一句话:二进制形式
client_socket.send("欢迎来到服务器".encode("utf-8"))
# 6、接收客户端发过来的回执信息(二进制),需要解码为字符串。
# 1023表示一次性接收客户端发送的数据的最大长度(字节),超出长度则无法接收
recv_data_bytes = client_socket.recv(1024)
recv_data_str = recv_data_bytes.decode("utf-8")
print(f"服务器端接收到客户端:{client_addr},的回执信息:{recv_data_str}")
if recv_data_str == "exit":
break
# 7、释放资源,关闭Socket
client_socket.close()
serve_socket.close()
客户端
客户端的开发步骤大致可以分为如下五个步骤:
- 创建Socket对象。(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
- 创建与服务器端的连接。(connect()函数,参数为元组,包含ip地址和端口号)
- 向服务器端发送数据。(send()函数,参数为字符串,会自动编码为二进制数据)
- 接收服务器端的数据。(recv()函数,接收数据,返回一个元组,包含数据,和客户端的连接信息,且最大接收字节长度为1024字节)
- 释放内存
下面代码将演示完整的服务器端开发步骤:
# 客户端代码
import socket
# 1、创建客户端端Socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("客户端启动成功")
# 2、连接服务器端IP和端口号
# 此处的IP地址和端口号,必须和服务器端一致
client_socket.connect(("127.0.0.1", 12344))
print("连接服务器成功")
# 给服务器端源源不断的发送一句话,二进制格式
while True:
# 3、接收服务端发送过来的消息(二进制)需要解码为字符串
data = input("请输入要给服务器发送的消息:")
# 4、给服务器端发送一句话
client_socket.send(data.encode("utf-8"))
if data == "exit":
break
# 5、释放资源,关闭Socket
client_socket.close()
# 4、给服务器端发送一句话
client_socket.send(data.encode("utf-8"))
if data == "exit":
break
# 5、释放资源,关闭Socket
client_socket.close()
在完成服务器端和客户端部分的代码后,就可以就可以运行这两部分代码进行数据传输了。(先运行服务器端,后运行客户端。)