python學(xué)習(xí)教程之socket庫的基本使用(網(wǎng)絡(luò)編程-套接字)
一、關(guān)于 socket 的介紹
Socket 又稱 "套接字",應(yīng)用程序通常通過 "套接字" 向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答網(wǎng)絡(luò)請求,使主機間或者一臺計算機上的進程間可以通訊。python中提供了兩個基本的 Socket 模塊:服務(wù)端 Socket 和客戶端 Socket,當創(chuàng)建了一個服務(wù)端 Socket 后,這個 Socket 就會在本機的一個端口上等待連接,當客戶端 Socket 訪問這個端口,兩者完成連接后就能夠進行交互了。
二、創(chuàng)建套接字對象(Socket 的實例化)
在使用 Socket 進行編程時,需要先實例化一個 Scoket 類,Python 中,我們用 socket()函數(shù)來創(chuàng)建套接字。
關(guān)于 socket 函數(shù)的用法:
scoket(family,type[,protocol])
第一個參數(shù) family 是指定應(yīng)用程序使用的通信協(xié)議的協(xié)議族,有:
Family參數(shù) | 描述 |
socket.AF_UNIX | 只能夠用于單一的Unix系統(tǒng)進程間通信 |
socket.AF_INET | 服務(wù)器之間網(wǎng)絡(luò)通信 |
socket.AF_INET6 | IPv6 |
默認值為 AF_INET
第二個參數(shù) type 為要創(chuàng)建套接字的類型
Type參數(shù) | 描述 |
socket.SOCK_STREAM | 流式socket , 當使用TCP時選擇此參數(shù) |
socket.SOCK_DGRAM | 數(shù)據(jù)報式socket ,當使用UDP時選擇此參數(shù) |
socket.SOCK_RAW | 原始套接字,允許對底層協(xié)議如IP、ICMP進行直接訪問 |
第三個參數(shù) protocol 是可選項,指明所要接收的協(xié)議類型,通常為 0 或者不填。
Type參數(shù) | 描述 |
socket.IPPROTO_RAW | 相當于protocol=255,此時socket只能用來發(fā)送IP包,而不能接收任何的數(shù)據(jù)。發(fā)送的數(shù)據(jù)需要自己填充IP包頭,并且自己計算校驗和。 |
socket.IPPROTO_IP | 相當于protocol=0,此時用于接收任何的IP數(shù)據(jù)包。其中的校驗和和協(xié)議分析由程序自己完成。 |
接下來我們實例化一個簡單的 TCP 類型的 Socket
測試代碼:
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print(s) print(type(s))
代碼解釋:
- 首先肯定需要使用 import 導(dǎo)入 socket 庫;
- 用一個自定義參數(shù)(我這里用的 s )來接收創(chuàng)建的套接字對象;
- 輸出套接字對象以及它的類型。
運行結(jié)果:
關(guān)于運行結(jié)果的解釋:
fd=332: 表示套接字的文件描述符(file descriptor),在此處為332。
family=2: 表示套接字的地址族(address family),這里是IPv4地址族(AF_INET)。
type=1: 表示套接字的類型(socket type),這里是流式套接字(SOCK_STREAM),用于TCP協(xié)議。
proto=0: 表示套接字使用的協(xié)議,這里是默認協(xié)議(通常與套接字類型相關(guān))。
<class 'socket.socket'>: 表示所創(chuàng)建的對象屬于Python的socket模塊中的socket類。
三、套接字對象方法(Socket 常用函數(shù))
首先介紹服務(wù)端函數(shù)
1、bind 函數(shù)
該函數(shù)是服務(wù)端函數(shù),會將之前創(chuàng)建的套接字與指定的IP地址和端口進行綁定,使用點直接調(diào)用該方法,以元組(host, port)的形式表示地址。
比如我們綁定本地的 12345 端口:
s.bind(('127.0.0.1', 12345))
注意這里用到了兩次括號,因為 bind 方法的參數(shù)需要是一個包含主機地址和端口號的元組。
2、listen 函數(shù)
該函數(shù)也是服務(wù)端函數(shù),用于在使用TCP的服務(wù)端開啟監(jiān)聽模式,只有一個參數(shù),指定在拒絕連接之前,操作系統(tǒng)可以掛起的最大連接數(shù)量,該值至少為1,大部分應(yīng)用程序設(shè)為 5 即可。
在服務(wù)端開啟監(jiān)聽,設(shè)置操作系統(tǒng)可以掛起的最大連接數(shù)量為 5 :
s.listen(5)
listen() 只是讓套接字處于監(jiān)聽狀態(tài),并沒有接收請求,接收請求需要使用 accept() 函數(shù)。
3、accept 函數(shù)
當套接字處于監(jiān)聽狀態(tài)時,可以通過 accept() 函數(shù)來接收客戶端請求,該函數(shù)也是服務(wù)端函數(shù),接受 TCP 連接并返回(conn,address),返回一個新的套接字來和客戶端通信,其中 conn 是新的套接字對象,可以用來接收和發(fā)送數(shù)據(jù),address 是連接客戶端的地址。
比如我們就使用 conn 和 address 這兩個參數(shù)(可自定義)來接收 accept 函數(shù)返回的值
conn, address = s.accept()
下面介紹客戶端函數(shù)
4、connect 與 connect_ex 函數(shù)
connect() 是客戶端程序用來連接服務(wù)端的方法,客戶端連接到 address 處的套接字,一般 address 的格式為元組(host, port),如果連接出錯,會返回 socket.error 錯誤。
比如我們連接到剛才創(chuàng)建的套接字,即本地的 12345 端口:
import socket c = socket.socket() c.connect(('127.0.0.1', 12345))
只有經(jīng)過 connect 連接成功后的套接字對象才能調(diào)用發(fā)送和接受方法(send/recv),所以服務(wù)端的 s 對象不能 send 或者 recv 。
還有一個 connect_ex 函數(shù),功能與 connect 相同,只是成功返回 0,失敗返回 error 的值。
下面是一些常見的公共函數(shù)
5、send 、 sendall 、sendto 函數(shù)
send() :用于發(fā)送 TCP 數(shù)據(jù)
用法:s.send(string[,flag])
將 string 中的數(shù)據(jù)發(fā)送到連接的套接字,返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于 string 的字節(jié)大小。
sendall() :完整發(fā)送TCP數(shù)據(jù)
用法:s.sendall(string[,flag])
與 send() 類似,將 string 中的數(shù)據(jù)發(fā)送到連接的套接字,但在返回之前會嘗試發(fā)送所有數(shù)據(jù),成功返回None,失敗則拋出異常。
關(guān)于參數(shù)的說明:
string: 這是要發(fā)送的數(shù)據(jù),通常是一個字符串。這是必需的參數(shù)。
flag : 這是一個可選的參數(shù),用于指定發(fā)送數(shù)據(jù)的附加選項,在大多數(shù)情況下可以省略。
比如我們將 "Hello, server!" 字符串通過UTF-8編碼轉(zhuǎn)換為字節(jié)數(shù)據(jù),然后使用套接字的 send 方法發(fā)送這些字節(jié)數(shù)據(jù)到連接的服務(wù)端:
c.send("Hello, server!".encode('utf-8'))
sendto :用于發(fā)送 UDP 數(shù)據(jù)
用法:s.sendto(string[,flag],address)
將數(shù)據(jù)發(fā)送到套接字,address是形式為(ipaddr,port)的元組,指定遠程地址,返回值是發(fā)送的字節(jié)數(shù)。
6、recv 與 recvfrom 函數(shù)
recv :接受TCP套接字的數(shù)據(jù),數(shù)據(jù)以字符串形式返回。
用法:s.recv(bufsize[,flag])
參數(shù)說明:
bufsize: 這是一個整數(shù),表示要接收的最大字節(jié)數(shù)。接收的實際數(shù)據(jù)可能少于或等于這個值,取決于發(fā)送端發(fā)送的數(shù)據(jù)量。
flag(可選): 這是一個可選的參數(shù),用于指定接收數(shù)據(jù)的附加選項。在大多數(shù)情況下,可以省略這個參數(shù)。
通過 recv 方法接收最多 1024 字節(jié)的數(shù)據(jù),我們將接收到的字節(jié)數(shù)據(jù)解碼為 UTF-8 編碼的字符串,最后打印出來:
re = c.recv(1024) print(re.decode('utf-8'))
recvfrom:接受 UDP 套接字的數(shù)據(jù),與 recv() 類似,但返回值是(data, address)。其中 data 包含接收數(shù)據(jù)的字符串,address 是發(fā)送數(shù)據(jù)的套接字地址。
特別說明:recvfrom 函數(shù)是可以在沒有進行 connect 的情況下使用的,對于 UDP 套接字,可以在未連接的狀態(tài)下使用 recvfrom 來接收數(shù)據(jù)。recvfrom 通常與 UDP 一起使用,因為 UDP 是一個無連接協(xié)議,而 recvfrom 提供了從發(fā)送端獲取地址信息的能力。在 TCP 中,由于是面向連接的,地址信息通常在連接建立時就已經(jīng)確定了,所以 recv 通常就足夠了。
示例:
import socket # 創(chuàng)建一個UDP套接字 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 綁定本地地址和端口 s.bind(('127.0.0.1', 12345)) # 接收數(shù)據(jù),設(shè)置bufsize為最大接收字節(jié)數(shù) data, address = s.recvfrom(1024) # 打印接收到的數(shù)據(jù)和發(fā)送端地址信息 print(f"Received data: {data.decode('utf-8')}") print(f"Received from: {address}")
7、close 函數(shù)
該函數(shù)用于關(guān)閉套接字
直接使用點調(diào)用即可
s.close()
三、簡單的服務(wù)端和客戶端示例
服務(wù)端代碼:
import socket # 創(chuàng)建一個TCP套接字 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 綁定主機和端口 server_socket.bind(('127.0.0.1', 12345)) # 監(jiān)聽連接 server_socket.listen() print("Server is listening for incoming connections...") # 接受客戶端連接 client_socket, client_address = server_socket.accept() print(f"Connection established with {client_address}") # 接收數(shù)據(jù) data = client_socket.recv(1024) print(f"Received data: {data.decode('utf-8')}") # 發(fā)送響應(yīng) response = "Hello, client!" client_socket.send(response.encode('utf-8')) # 關(guān)閉連接 client_socket.close() server_socket.close()
客戶端代碼:
import socket # 創(chuàng)建一個TCP套接字 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 連接到服務(wù)器 client_socket.connect(('127.0.0.1', 12345)) # 發(fā)送數(shù)據(jù) data_to_send = "Hello, server!" client_socket.send(data_to_send.encode('utf-8')) # 接收響應(yīng) response = client_socket.recv(1024) print(f"Received response: {response.decode('utf-8')}") # 關(guān)閉連接 client_socket.close()
先開啟服務(wù)端,再運行客戶端
運行效果:
四、關(guān)于 socket 庫相關(guān)方法函數(shù)的總結(jié)
Socket 創(chuàng)建和配置:
socket(family, type, proto=0, fileno=None):創(chuàng)建一個套接字對象。
gethostname():獲取主機名。
通用套接字方法:bind(address):將套接字綁定到指定的地址。
listen(backlog):開始監(jiān)聽傳入連接請求。
accept():接受連接,返回新的套接字和對端地址。
connect(address):連接到遠程套接字。
close():關(guān)閉套接字。
數(shù)據(jù)收發(fā):send(bytes):發(fā)送數(shù)據(jù)。
recv(bufsize):接收數(shù)據(jù)。
UDP 相關(guān)方法:sendto(data, address):發(fā)送UDP數(shù)據(jù)到指定地址。
recvfrom(bufsize):接收UDP數(shù)據(jù)和對端地址。設(shè)置和獲取套接字選項:
setsockopt(level, optname, value):設(shè)置套接字選項。
getsockopt(level, optname, buflen=None):獲取套接字選項。獲取主機信息:
gethostbyname(hostname):通過主機名獲取IP地址。
gethostbyaddr(ip_address):通過IP地址獲取主機名。
總結(jié)
到此這篇關(guān)于python學(xué)習(xí)教程之socket庫的基本使用的文章就介紹到這了,更多相關(guān)python socket庫基本使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python分支語句與循環(huán)語句應(yīng)用實例分析
這篇文章主要介紹了Python分支語句與循環(huán)語句應(yīng)用,結(jié)合具體實例形式詳細分析了Python分支語句與循環(huán)語句各種常見應(yīng)用操作技巧與相關(guān)注意事項,需要的朋友可以參考下2019-05-05Python辦公自動化之發(fā)送電子郵件和Outlook集成
Python辦公?動化是利?Python編程語?來創(chuàng)建腳本和程序,以簡化、加速和?動化?常辦公任務(wù)和?作流程的過程,本文主要介紹一下如何利用Python實現(xiàn)發(fā)送電子郵件和Outlook集成,需要的可以參考下2023-12-12Python的內(nèi)建模塊itertools的使用解析
這篇文章主要介紹了Python的內(nèi)建模塊itertools的使用解析,itertools是python的迭代器模塊,itertools提供的工具相當高效且節(jié)省內(nèi)存,Python的內(nèi)建模塊itertools提供了非常有用的用于操作迭代對象的函數(shù),需要的朋友可以參考下2023-09-09