Python Socket的介紹與簡單使用
Socket 簡介
Socket模塊的主要目的就是幫助在網絡上的兩個程序之間建立信息通道。在python中提供了兩個基本的Socket模塊:服務端Socket和客戶端Socket。當創建了一個服務端Socket之後,這個Socket就會在本機的一個端口上等待連接,客戶端Socket會訪問這個端口,當兩者完成連接之後就能夠進行交互了。在使用Socket進行編程時,需要先實例化一個Scoket類。
使用Socker建立服務端的思路主要是首先實例化一個 Socket類,然後開始循環監聽,一直可以接收來自客戶端的連接。成功建立連接之後,接收客戶端發來的數據,並再向客戶端發送數據,傳輸完畢之後,關閉這次連接。
使用Socket建立客戶端則要簡單得多,在實例化一個Socket類之後,連接一個遠程的地址,這個地址由IP和端口組成。成功建立連接之後,開始發送和接收數據,傳輸完畢之後,關閉這次連接。
基本用法
一、Socket的實例化
實例化的格式爲:
scoket(family,type[,protocal])
其中第一個參數family表示地址族,常用的協議族有:AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE等,默認值爲AF_INET,通常使用這個即可。
第二個參數表示Socket類型,這裏使用的值有三個:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW。
SOCK_STREAM是TCP類型,保證數據順序以及可靠性;
SOCK_DGRAM是UDP類型,不保證數據接收的順序,非可靠連接;
SOCK_RAW是原始類型,允許對底層協議如IP、ICMP進行直接訪問,基本不會用到。
默認值是第一個。
第三個參數是指定協議,這個是可選的,通常賦值爲0,由系統選擇。
例如想初始化一個TCP類型的Socket,語句如下:
x = socket.socket()
這條語句相當於:
x = socket.socket(sokcet.AF_INET, socket.SOCK_STREAM)
因爲這裏都是默認值所以可以省略掉
而如果想初始化一個UDP類型,則語句如下:
x = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
二、Socket常用的函數
當成功初始化一個 Socket之後,就可以使用Socket類所提供的函數。Socket類中主要提供如下所示常用的函數:
bind():這個函數由服務端Socket調用,會將之前創建Socker與指定的IP地址和端口進行綁定。如果之前使用了AF_INET初始化Socket,那麼這裏可以使用元組(host, port) 的形式表示地址。
例如,要將剛纔創建的Socket套接字綁定到本機的2345端口,就可以使用如下語句:
x.bind(("127.0.0.1",234511))
listen():這個函數用於在使用TCP的服務端開啓監聽模式。這個函數可以使用個參數來指定可以掛起的最大連接數量。這個參數的值最小爲1,般設置爲5。
例如,要在服務端開啓一個監聽, 可以使用如下語句:
x.l1sten(5)
accept():這個函數用於在使用TCP的服務端接收連接,一般是阻塞態。接受TCP連接並返回(conn,adresse), 其中,conn 是新的套接字對象,可以用來接收和發送數據; address是連接客戶端的地址。
以上三個函數是用於服務端的Socket 函數,,,
connect():這個兩數用於在使用TCP的客戶端去連接服務端時使用,使用的參數是一個元組,形式爲(hostname, port)。
例如,在客戶端程序初始化了一個Socker 之後,就可以使用這個函數去連接到服務端。例如,現在要連接本機的2345端口,可以使用如下語句:
x.connect (("127.0.0.1",2345))
send():這個函數用於在使用TCP時發送數據,完整的形式爲send(string[,flag])
利用這個函數可以將string代表的數據發送到已經連接的Socket,返回值是發送字節的數量。但是可能未將指定的內容全部發送。
sendall():這個函數與send()相類似,也是用於在使用TCP時發送數據,完整的形式爲sendall(string[,falg]),與send()的區別是完整發送TCP數據。將string中的數據發送到連接的套接字,但在返回之前會嘗試發送所有數據。成功返回None,失敗則拋出異常。
例如,使用這個函數發送一段字符到Socket,可以使用如下語句:
x.sendall(bytes("Hello. My Friend! ", encoding="utf-8"))
recv():這個兩數用於在使用TCP時接收數據,完整的形式爲recv(bufsize[,flag]),接收Soker的數據。數據以字符串形式返回,bufsize指定最多可以接收的數量,flag這個參數一般不會使用。
例如,通過這個函數接收一段長度爲1024的字符Socket,可以使用如下語句:
obj.recv(1024)
sendto():這個函數用於在使用UDP時發送數據,完整的形式爲sendto(string[,flag],address),返回值是發送的字節數。address 是形式爲(ipaddr,port) 的元組,指定遠程地址。
recvfrom(): UDP專用,接收數據,返回數據遠端的IP地址和端口,但返回值是(data,address)。其中,data 是包含接收數據的字符事,adress 是發送數據的套接字地址。
closc():關閉socket。
使用Socket編寫一個簡單的服務端和客戶端
服務端:
import socket
x = socket.socket()
x.bind(("127.0.0.1",1234))
x.listen(5)
while True:
conn,address = x.accept()
print("A new connent from ", address)
conn.sendall(bytes("Hello! A_dmin!!",encoding="utf-8"))
conn.close()
客戶端:
import socket
x = socket.socket()
x.connect(("127.0.0.1",1234))
data = x.recv(1024)
x.close()
print("Received " + repr(data))
效果如下: