1、网络通信
简单来说,网络是用物理链路将各个孤立的工作站或主机相连在一起,组成数据链路,从而达到资源共享和通信的目的。
使用网络的目的,就是为了联通多方然后进行通信,即把数据从一方传递给另外一方。
前面的学习编写的程序都是单机的,即不能和其他电脑上的程序进行通信。为了让在不同的电脑上运行的软件,之间能够互相传递数据,就需要借助网络的功能。
使用网络能够把多方链接在一起,然后可以进行数据传递
所谓的网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信
2、socket概念
socket(简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:
它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的
例如我们每天浏览网页、QQ 聊天、收发 email 等等。所以socket在网络通信的时候是很重要的。
2.1 创建套接字
在python中我们可以直接导入socket这个模块来创建
import socket
socket.socket()
这样我们也就创建好了一个socket连接,但是里面还有两个参数
- Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
- Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)
创建套接字连接主要有三步:
1、创建套接字
2、使用套接字来进行收、发数据
3、关闭套接字
今天我们也主要来讲udp协议
3、UDP协议
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议。在通信开始之前,不需要建立相关的链接,只需要发送数据即可,类似于生活中,“写信”。
3.1创建udp协议
- 创建一个udp协议也是按照上面的三步来走
#首先导入socket模块
import socket
# 1、创建套接字
# socket.AF_INET(用于Internet之间通信) socket.SOCK_DGRAM(用于udp协议)
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#2、使用套接字来进行接收和发送消息
#3、关闭套接字
udp_socket.close()
3.2udp协议之发送数据
发送数据主要使用的是sendto(data: bytes, address: _Address),这个方法需要两个参数:
- data 是你需要发送的数据,注意看类型 是一个二进制数据
- address 接收方的地址,这是一个元组的形式(addr_ip,port)
import socket
# 1、创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#2、使用套接字来进行发送数据
udp_socket.sendto('你好'.encode('utf-8'),('192.168.0.102',8989))
#3、关闭套接字
udp_socket.close()
上面就是一个udp协议发送数据的过程,在这里主要注意的地方是发送数据的时候,要进行一个编码,我们要把发送的数据转换成一个二进制数
在进行测试的时候,我们可以借助一个网络调试助手
来进行练习
打开这个网络调试助手
后,我们先在左上方进行绑定端口,然后运行程序,这样就可以接收到数据了
3.3 udp协议之接收数据
在进行接收数据的时候,我们要先进行端口的绑定,因为在别人给我们发送数据的时候,需要有一个ip地址和端口,这样才可以准确的把信息发送给我们
import socket
# 1、创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2、绑定端口
udp_socket.bind(('',9090))
#3、使用套接字来进行接收数据
recv_data = udp_socket.recvfrom(1024)
print(recv_data)
#3、关闭套接字
udp_socket.close()
在接收数据的时候,我们用的是recvfrom()
这个方法,在这个方法里面有一个1024
,表示一次可以接收1024个字节,这个方法接收到数据之后会有一个返回值,这个返回值是一个元组的形式,元组的第一个元素是发送方发送的数据,第二个元素是发送方的ip地址和端口号
我在运行程序之后,你会发现程序是一种阻塞
的状态,是因为recvfrom()
这个方法一直在等待发送方给我们发送数据
当我们使用网络调试助手
给9090这个端口发送数据之后,那边会立即收到数据并打印,但是细心的也会发现打印出来的数据是一个二进制的形式,而我们发送的是“你好”,这是因为编码所导致的,这个时候我们就需要用decode()
这个方法来进行转码
因为我发送方发送的是gbk
形式的编码,所以我也需要转换成gbk
形式
recv_data,recv_addr = udp_socket.recvfrom(1024)
print(recv_data.decode('gbk'),recv_addr)
在接收数据的时候,我使用了拆包
来进行接收数据,然后我们运行再打印看看
这个时候就可以正常显示了
总结
- 一个udp网络程序,可以不绑定,此时操作系统会随机进行分配一个端口,如果重新运行此程序端口可能会发生变化
- 一个udp网络程序,也可以绑定信息(ip地址,端口号),如果绑定成功,那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的