Python中的网络编程之UDP
Python中的網(wǎng)絡(luò)編程之UDP
文章目錄
- Python中的網(wǎng)絡(luò)編程之UDP
- 一、Socket編程
- `1.什么是客戶(hù)端/服務(wù)器架構(gòu)`?
- **`2.套接字:通信端點(diǎn)`**
- 3.套接字地址:主機(jī)-端口對(duì)
- 4.套接字類(lèi)型
- 二、常見(jiàn)的套接字對(duì)象方法和屬性
- 三、創(chuàng)建套接字
- 四、UDP網(wǎng)絡(luò)程序
- 五、UDP的綁定端口問(wèn)題
- 六、UDP聊天器
- 七、python3編碼轉(zhuǎn)換
一、Socket編程
1.什么是客戶(hù)端/服務(wù)器架構(gòu)?
服務(wù)器就是一系列硬件或軟件,為一個(gè)或多個(gè)客戶(hù)端(服務(wù)的用戶(hù))提供所需的“服務(wù)”。它存在唯一目的就是等待客戶(hù)端的請(qǐng)求,并響應(yīng)它們(提供服務(wù)),然后等待更多請(qǐng)求。說(shuō)白了就是一個(gè)提供服務(wù),一個(gè)請(qǐng)求服務(wù)得到相應(yīng)的一個(gè)過(guò)程。
2.套接字:通信端點(diǎn)
套接字是計(jì)算機(jī)網(wǎng)絡(luò)數(shù)據(jù)結(jié)構(gòu),它體現(xiàn)了上節(jié)中描述的“通信端點(diǎn)”的概念。在任何類(lèi)型的通信開(kāi)始之前,網(wǎng)絡(luò)應(yīng)用程序必須創(chuàng)建套接字。
可以將它們比作電話(huà)插孔,沒(méi)有它將無(wú)法進(jìn)行通信。
Python只支持AF_UNIX、AF_NETLINK、AF_TIPC 和 AF_INET ,重點(diǎn)使用基于網(wǎng)絡(luò)的AF_INET.
3.套接字地址:主機(jī)-端口對(duì)
它是網(wǎng)絡(luò)通信過(guò)程中端點(diǎn)的抽象表示,python使用元組保存:ADDR =(HOST,PORT)。
4.套接字類(lèi)型
流式套接字(SOCK_STREAM):用于提供面向連接、可靠的數(shù)據(jù)傳輸服務(wù)。
數(shù)據(jù)報(bào)套接字(SOCK_DGRAM):提供了一種無(wú)連接的服務(wù)。該服務(wù)并不能保證數(shù)據(jù)傳輸?shù)目煽啃?#xff0c;數(shù)據(jù)有可能在傳輸過(guò)程中丟失或出現(xiàn)數(shù)據(jù)重復(fù),且無(wú)法保證順序地接收到數(shù)據(jù)。
二、常見(jiàn)的套接字對(duì)象方法和屬性
| 服務(wù)端 | 服務(wù)器套接字方法 |
| s.bind(ADDR) 將地址 | (主機(jī)名、端口號(hào)對(duì))綁定到套接字上 |
| s.listen([backlog]) | 設(shè)置并啟動(dòng) TCP 監(jiān)聽(tīng)器,如果指定backlog,則必須至少為0(如果低于0,則設(shè)置為0); |
| s.accept() | 被動(dòng)接受 TCP 客戶(hù)端連接,一直等待直到連接到達(dá)(阻塞) |
| 客戶(hù)端 | 客戶(hù)端套接字方法 |
| s.connect() | 主動(dòng)發(fā)起 TCP 服務(wù)器連接 |
| s.connect_ex() | connect()的擴(kuò)展版本,此時(shí)會(huì)以錯(cuò)誤碼的形式返回問(wèn)題,而不是拋出一個(gè)異常 |
| 普通通用 | 普通的套接字方法 |
| s.recv() | 接收 TCP 消息 |
| s.recv_into() | 接收 TCP 消息到指定的緩沖區(qū) |
| s.send() | 發(fā)送 TCP 消息 |
| s.sendall() | 完整地發(fā)送 TCP 消息 |
| s.recvfrom() | 接收 UDP 消息 |
| s.recvfrom_into() | 接收 UDP 消息到指定的緩沖區(qū) |
| s.sendto() | 發(fā)送 UDP 消息 |
| s.getpeername() | 連接到套接字(TCP)的遠(yuǎn)程地址 |
| s.getsockname() | 當(dāng)前套接字的地址 |
| s.getsockopt() | 返回給定套接字選項(xiàng)的值 |
| s.setsockopt() | 設(shè)置給定套接字選項(xiàng)的值 |
| s.shutdown() | 關(guān)閉連接 |
| s.close() | 關(guān)閉套接字 |
| s.detach() | 在未關(guān)閉文件描述符的情況下關(guān)閉套接字,返回文件描述符 |
| s.ioctl() | 控制套接字的模式(僅支持 Windows) |
| 阻塞 | 面向阻塞的套接字方法 |
| s.setblocking() | 設(shè)置套接字的阻塞或非阻塞模式 |
| s.settimeout() | 設(shè)置阻塞套接字操作的超時(shí)時(shí)間 |
| s.gettimeout() | 獲取阻塞套接字操作的超時(shí)時(shí)間 |
| 文件方法 | 面向文件的套接字方法 |
| s.fileno() | 套接字的文件描述符 |
| s.makefile() | 創(chuàng)建與套接字關(guān)聯(lián)的文件對(duì)象 |
| 屬性 | 數(shù)據(jù)屬性 |
| s.family | 套接字家族 |
| s.type | 套接字類(lèi)型 |
| s.proto | 套接字協(xié)議 |
三、創(chuàng)建套接字
函數(shù) socket.socket 創(chuàng)建一個(gè) socket,該函數(shù)帶有兩個(gè)參數(shù):
- Address Family:可以選擇 AF_INET(用于 Internet 進(jìn)程間通信) 或者 AF_UNIX(用于同一臺(tái)機(jī)器進(jìn)程間通信),實(shí)際工作中常用AF_INET
- Type:套接字類(lèi)型,可以是 SOCK_STREAM( 流式套接字,主要用于 TCP 協(xié)議)或者SOCK_DGRAM(數(shù)據(jù)報(bào)套接字, 主要用于 UDP 協(xié)議)
創(chuàng)建一個(gè)tcp socket(tcp套接字):
import socket# 創(chuàng)建tcp的套接字 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# ...這里是使用套接字的功能(省略)...# 不用的時(shí)候,關(guān)閉套接字 s.close()創(chuàng)建一個(gè)udp socket(udp套接字):
import socket# 創(chuàng)建udp的套接字 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# ...這里是使用套接字的功能(省略)...# 不用的時(shí)候,關(guān)閉套接字 s.close()套接字使用流程 與 文件的使用流程很類(lèi)似
- 創(chuàng)建套接字
- 使用套接字收/發(fā)數(shù)據(jù)
- 關(guān)閉套接字
四、UDP網(wǎng)絡(luò)程序
創(chuàng)建一個(gè)基于udp的網(wǎng)絡(luò)程序流程,具體步驟如下:
- 創(chuàng)建套接字
- 發(fā)送/接收數(shù)據(jù)
- 關(guān)閉套接字
代碼–發(fā)送數(shù)據(jù):
#coding=utf-8from socket import *# 1. 創(chuàng)建udp套接字 udp_socket = socket(AF_INET, SOCK_DGRAM)# 2. 準(zhǔn)備接收方的地址 # '192.168.1.103'表示目的ip地址 # 8080表示目的端口 dest_addr = ('192.168.1.103', 8080) # 注意 是元組,ip是字符串,端口是數(shù)字# 3. 從鍵盤(pán)獲取數(shù)據(jù) send_data = input("請(qǐng)輸入要發(fā)送的數(shù)據(jù):")# 4. 發(fā)送數(shù)據(jù)到指定的電腦上的指定程序中 udp_socket.sendto(send_data.encode('utf-8'), dest_addr)# 5. 關(guān)閉套接字 udp_socket.close()代碼–發(fā)送接收數(shù)據(jù):
#coding=utf-8from socket import *# 1. 創(chuàng)建udp套接字 udp_socket = socket(AF_INET, SOCK_DGRAM)# 2. 準(zhǔn)備接收方的地址 dest_addr = ('192.168.236.129', 8080)# 3. 從鍵盤(pán)獲取數(shù)據(jù) send_data = input("請(qǐng)輸入要發(fā)送的數(shù)據(jù):")# 4. 發(fā)送數(shù)據(jù)到指定的電腦上 udp_socket.sendto(send_data.encode('utf-8'), dest_addr)# 5. 等待接收對(duì)方發(fā)送的數(shù)據(jù) recv_data = udp_socket.recvfrom(1024) # 1024表示本次接收的最大字節(jié)數(shù)# 6. 顯示對(duì)方發(fā)送的數(shù)據(jù) # 接收到的數(shù)據(jù)recv_data是一個(gè)元組 # 第1個(gè)元素是對(duì)方發(fā)送的數(shù)據(jù) # 第2個(gè)元素是對(duì)方的ip和端口 print(recv_data[0].decode('gbk')) print(recv_data[1])# 7. 關(guān)閉套接字 udp_socket.close()五、UDP的綁定端口問(wèn)題
一般情況下,在一臺(tái)電腦上運(yùn)行的網(wǎng)絡(luò)程序有很多,為了不與其他的網(wǎng)絡(luò)程序占用同一個(gè)端口號(hào),往往在編程中,udp的端口號(hào)一般不綁定
但是如果需要做成一個(gè)服務(wù)器端的程序的話(huà),是需要綁定的,想想看這又是為什么呢?
如果報(bào)警電話(huà)每天都在變,想必世界就會(huì)亂了,所以一般服務(wù)性的程序,往往需要一個(gè)固定的端口號(hào),這就是所謂的端口綁定
#coding=utf-8from socket import *# 1. 創(chuàng)建套接字 udp_socket = socket(AF_INET, SOCK_DGRAM)# 2. 綁定本地的相關(guān)信息,如果一個(gè)網(wǎng)絡(luò)程序不綁定,則系統(tǒng)會(huì)隨機(jī)分配 local_addr = ('', 7788) # ip地址和端口號(hào),ip一般不用寫(xiě),表示本機(jī)的任何一個(gè)ip udp_socket.bind(local_addr)# 3. 等待接收對(duì)方發(fā)送的數(shù)據(jù) recv_data = udp_socket.recvfrom(1024) # 1024表示本次接收的最大字節(jié)數(shù)# 4. 顯示接收到的數(shù)據(jù) print(recv_data[0].decode('gbk'))# 5. 關(guān)閉套接字 udp_socket.close()六、UDP聊天器
import socketdef send_msg(udp_socket):"""獲取鍵盤(pán)數(shù)據(jù),并將其發(fā)送給對(duì)方"""# 1. 從鍵盤(pán)輸入數(shù)據(jù)msg = input("\n請(qǐng)輸入要發(fā)送的數(shù)據(jù):")# 2. 輸入對(duì)方的ip地址dest_ip = input("\n請(qǐng)輸入對(duì)方的ip地址:")# 3. 輸入對(duì)方的portdest_port = int(input("\n請(qǐng)輸入對(duì)方的port:"))# 4. 發(fā)送數(shù)據(jù)udp_socket.sendto(msg.encode("utf-8"), (dest_ip, dest_port))def recv_msg(udp_socket):"""接收數(shù)據(jù)并顯示"""# 1. 接收數(shù)據(jù)recv_msg = udp_socket.recvfrom(1024)# 2. 解碼recv_ip = recv_msg[1]recv_msg = recv_msg[0].decode("utf-8")# 3. 顯示接收到的數(shù)據(jù)print(">>>%s:%s" % (str(recv_ip), recv_msg))def main():# 1. 創(chuàng)建套接字udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 2. 綁定本地信息udp_socket.bind(("", 7890))while True:# 3. 選擇功能print("="*30)print("1:發(fā)送消息")print("2:接收消息")print("="*30)op_num = input("請(qǐng)輸入要操作的功能序號(hào):")# 4. 根據(jù)選擇調(diào)用相應(yīng)的函數(shù)if op_num == "1":send_msg(udp_socket)elif op_num == "2":recv_msg(udp_socket)else:print("輸入有誤,請(qǐng)重新輸入...")if __name__ == "__main__":main()七、python3編碼轉(zhuǎn)換
str->bytes:encode編碼
bytes->str:decode解碼
字符串通過(guò)編碼成為字節(jié)碼,字節(jié)碼通過(guò)解碼成為字符串。
其中decode()與encode()方法可以接受參數(shù),其聲明分別為:
bytes.decode(encoding="utf-8", errors="strict") str.encode(encoding="utf-8", errors="strict")其中的encoding是指在解碼編碼過(guò)程中使用的編碼(此處指“編碼方案”是名詞),errors是指錯(cuò)誤的處理方案。
str.encode()
bytes.decode()
總結(jié)
以上是生活随笔為你收集整理的Python中的网络编程之UDP的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python中的协程
- 下一篇: Python中的网络编程之TCP