python中socket模块常用吗_python网络学习笔记——socket模块使用记录
此文章記錄了筆者學習python網絡中socket模塊的筆記。
建議初次學習socket的讀者先讀一遍socket模塊主要函數的介紹。
socket模塊的介紹可以參考筆者的前一篇關于socket官方文檔的學習記錄:python網絡學習筆記——socket模塊官方文檔學習記錄。
一個簡單地socket客戶端(TCP)代碼(如果不懂代碼含義可以看我上篇文章)
import socket #導入socket模塊
port =80 #端口
host="www.baidu.com" #主機地址
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #創建套接字
s.connect((host,port)) #套接字連接
#向網站發送請求,注意參數時byte類型。不能是str(python3.7)。
s.sendall(b'GET / HTTP/1.1\r\nHost:www.baidu.com\r\nConnection:keep-alive\r\n\r\n')
while 1:
#從網頁接受1024bytes大小的數據
buf=s.recv(1024)
#在無數據是跳出循環
if not len(buf):
break
#打印數據
print(buf)
簡單的一個客戶端程序,但并不嚴謹。
如果用戶給了一個不存在的主機地址或沒有服務的端口地址,那么在套接字連接的過程中:s.connect((host,port))會產生socket.gaierror。對上述程序可以用sys模塊中的exit函數和try關鍵字來完善。
將套接字連接改為:
try:
s.connect((host,port))
except socket.gaierror as e:
print(e)
#退出程序
sys.exit(1)
以上完善程序過程僅僅是一個引入。在使用網絡模塊時可能會產生各種各樣的異常,在編程寫程序時應盡量考慮到可能產生的異常與處理方法。其中try和except...as可能是我們調試時使用最多的工具了。
上述程序還有一個不方便的地方,就是數據呈現的方式。buf在每次循環得到的是一個1024字節的byte數據。byte數據在輸出時難以進行格式化的操作,并且1024字節大小的設置也很容易打亂原數據的格式。而套接字對象的makefile方法可以解決該問題。s.makefile(mode='r', buffering=None, *, encoding=None, errors=None, newline=None):
返回與套接字關聯的文件對象。返回的對象的具體類型取決于 makefile() 的參數。這些參數的解釋方式與內置的 open() 函數相同,其中 mode 的值僅支持 'r' (默認),'w' 和 'b'。
makefile方法將byte操作轉化為文件操作,這對數據的格式化操作提供了很大的便利。
所以,上述打印數據代碼都可以換為以下內容(建議找一個源碼比較少的網頁進行嘗試):
fd=s.makefile(mode='rb') #一定是rb,因為數據是byte類型
for i in fd.readlines(): #遍歷
print(i)
如果網頁的源碼過大的話,在打印過程中可能卡住。筆者在僅運行print(type(fd.readlines()))的情況下,電腦還是在1分鐘后給出結果。也可以使用fd.readline()進行數據第一行測試。
建立socket客戶端需要兩個步驟。首先建立socket對象,其次,將socket連接到遠程服務器上。
在建立ocket對象的時候,您需要告訴系統兩件事情:通信類型和協議家族。通信類型指明用什么協議來傳輸數據。協議的例子包括IPv4(當前的Intermet標準),IPv6(將來的Intermet.IPX/SPX(NerWare和AFP(Apple文件共享)。到目前為止,最通用的是IPv4;協議家族則定義數據如何被傳輸。協議家族一般是表示TCP通信的SOCKSTREAM或便是UDP的SOCK_DGRAM。
端口號
"端口"是英文port的意譯,可以認為是設備與外界通訊交流的出口。我們通過瀏覽器瀏覽的網頁一般是服務器的80端口。可自行百度常用端口地址。
UDP客戶端(不常用)
在socket被建立時,協議家族選擇SOCK_DGRAM。
UDP對數據的發送和接收沒有足夠的控制,在不調用connect方法時,可以通過sendto()方法和recvfrom()方法。s.recvfrom(bufsize[, flags]):
從套接字接收數據。返回值是一對 (bytes, address),其中 bytes 是字節對象,表示接收到的數據,address 是發送端套接字的地址。
s.sendto(bytes, flags, address):
發送數據給套接字。本套接字不應連接到遠程套接字,而應由 address 指定目標套接字。返回發送字節數。
基本服務器操作
簡單服務器代碼:
import socekt
host='' #空字符代表可以接受任何主機的連接
port=51423 #可以選擇任何一個大于1024的端口
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #創建套接字
s.bind((host, port)) #套接字綁定
s.listen(1) #監聽host的port,參數1表示最對有1個連接等待程序處理。
print("Server is running")
while True:
try:
##當有客戶端連接時,accept()方法會返回兩個信息,一個連接客戶端的套接字和連接主機地址
sock, addr = s.accept()
print(addr) #打印地址
except Exception as e:
print(e)
fd=sock.makefile(mode="rb')
print(fd.readline()) #打印數據第一行
fd.close() #關閉文件關聯
sock.close() #關閉客戶端套接字s.bind(address):
將套接字綁定到 address。套接字必須尚未綁定(套接字作為服務器時使用)。
s.listen([backlog]):
啟動一個作為服務器的套接字,用于接受連接(監聽,方法名很直觀)。如果指定 backlog,則它最低為 0(小于 0 會被置為 0),它指定系統允許暫未 accept 的連接數,超過后將拒絕新連接。未指定則自動設為合理的默認值 (套接字作為服務器時使用)。
s.accept():
接受一個連接。調用此方法的socket對象必須綁定到一個地址上并且監聽連接。返回值是一個 (conn, address) 對,其中 conn 是一個 新的套接字對象,用于在此連接上收發數據,address 是連接另一端的套接字所綁定的地址。(套接字作為服務器時使用)。
域名系統(DNS)
域名系統(DNS)是一個分布式的數據庫,主要用來把主機名轉換為IP地址。例如:將http://www.baidu.com 轉化為61.135.169.125。
socket的域名函數主要有:
socket.gethostbyname(host):
host是一個字符串的網址,返回解析之后的ip地址。
>>> socket.gethostbyname("www.baidu.com")
'61.135.169.125'
socket.gethostname():
無參數,返回本機的主機名。
>>> socket.gethostname()
'HOST-TEST' #已做處理
socket.gethostbyname_ex(hostname):
將主機名轉換為 IPv4 地址格式的擴展接口。返回三元組 (hostname, aliaslist, ipaddrlist),其中 hostname 是響應給定 ip_address 的主要主機名,aliaslist 是相同地址的其他可用主機名的列表(可能為空),而 ipaddrlist 是 IPv4 地址列表,包含相同主機名、相同接口的不同地址(通常是一個地址,但不總是如此)。(一個ip可能對應多個域名,一個域名也可對應多個ip。)
>>> socket.gethostbyname_ex('www.baidu.com')
('www.a.shifen.com', ['www.baidu.com'], ['61.135.169.121', '61.135.169.125'])
注:bind()函數的第一個參數為空時,意思為可以綁定多有接口和地址。在只希望一個特定的地址鏈接時,可以指定參數。
對數據進行完整性檢查,注意信息丟失情況的TCP更適合客戶端。而在服務器端,UDP不需要考慮丟包情況,更加適合。
死鎖發生在當一個服務器和客戶端同時往同一個連接上寫東西和同時從一個連接上讀的時候。在這些情況下,沒有進程可以得到任何的數據。
總結:
以上只是套接字的基礎使用。不過在使用python進行網絡編程時,socket模塊很少使用。python有更高級的網絡模塊。
ps.此專欄是筆者學習《python網絡編程基礎》的學習筆記。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的python中socket模块常用吗_python网络学习笔记——socket模块使用记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python画父子关系图_将有父子关系的
- 下一篇: 比亚迪计划明年在东莞量产新能源发动机,年