Pyhton的socket套接字之UDP编程
是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的。
创建socket 在 Python 中 使用socket 模块的函数 socket 就可以完成:
import socket
socket.socket(AddressFamily, Type)
函数 socket.socket 创建一个 socket,该函数带有两个参数:
- AddressFamily:可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
- Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)
示例代码:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #创建udp的套接字
#s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #创建tcp的套接字
# ...这里是使用套接字的功能(省略)...
# 不用的时候,关闭套接字
s.close()
套接字使用流程与文件的使用流程很类似:
- 创建套接字
- 使用套接字收/发数据
- 关闭套接字
UDP 不提供可靠性的传输,它只是把应用程序传给 IP 层的数据报发送出去,但是并不能保证它们能到达目的地。由于 UDP 在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
对于 UDP发送方流程, 有点类似于写信过程:
- 找个邮政工作人员(socket())
- 信封上写上地址同时里面装上信件内容并且投递(sendto() )
- 还可以继续写信,或者,接收对方的回信(recvfrom() )
- 打完收工(close() )
示例代码:
import socket
#1、创建套接字
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#2、发送数据
sendData = input("请输入要发送的数据:")
udp.sendto(sendData.encode("utf-8"), ("172.16.1.52", 8080))
#3、接收数据
recvData = udp.recvfrom(1024)
print("recvData = ", recvData)
#4、关闭套接字
udp.close()
UDP 发送方注意点
- 本地IP、本地端口(我是谁)
- 目的IP、目的端口(发给谁)
- 在发送方的代码中,我们只设置了目的IP、目的端口
- 发送方的本地 ip、本地 port 是我们调用 sendto 的时候系统底层自动给客户端分配的。分配端口的方式为随机分配,即每次运行系统给的 port 不一样。
python3编码转换
字符串通过编码成为字节码,字节码通过解码成为字符串:
str -> bytes: encode编码
bytes -> str: decode解码
示例如下:
>>> text = '我是文本'
>>> text
'我是文本'
>>> print(text)
我是文本
>>> bytesText = text.encode()
>>> bytesText
b'\xe6\x88\x91\xe6\x98\xaf\xe6\x96\x87\xe6\x9c\xac'
>>> print(bytesText)
b'\xe6\x88\x91\xe6\x98\xaf\xe6\x96\x87\xe6\x9c\xac'
>>> type(text)
<class 'str'>
>>> type(bytesText)
<class 'bytes'>
>>> textDecode = bytesText.decode()
>>> textDecode
'我是文本'
>>> print(textDecode)
我是文本
其中decode()与encode()方法可以接受参数,其声明分别为:
bytes.decode(encoding="utf-8", errors="strict")
str.encode(encoding="utf-8", errors="strict")
其中的encoding是指在解码编码过程中使用的编码(此处指“编码方案”是名词),errors是指错误的处理方案。
详细的可以参照官方文档:
元组拆包
>>> addr = ("127.0.0.1", 8888)
>>> ip, port = addr
>>> type(ip)
<class 'str'>
>>> type(port)
<class 'int'>
>>> print(ip)
127.0.0.1
>>> print(port)
8888
示例代码:
recvData, recvAddr = udp.recvfrom(1024)
print(recvAddr, " >>>>>>>>>>>>> ", recvData.decode("utf-8"))
接收端接收数据的条件
UDP网络程序想要收取数据需什么条件?
- 确定的 ip 地址
- 确定的端口(port)
这正如,我要收到别人寄过来的信,我必须告诉别人我的地址(ip),同时告诉别人我我的公寓信箱号(端口)。
接收端使用 bind() 函数,来完成地址结构与 socket 套接字的绑定,这样 ip、port 就固定了,发送端在 sendto 函数中指定接收端的 ip、port,就可以发送数据了。
2.3.4.2 示例代码
对于 UDP 服务器编程流程, 有点类似于收信过程:
- 找个邮政工作人员( socket() )
- 确定信箱的位置:地址+信箱号(bind() )
- 等待对方的来信( recvfrom() )
- 还可以回信(sendto() ),或者,继续等待对方的来信……
- 打完收工(close() )
评论 (0)