1. 程式人生 > 其它 >一文帶你瞭解Python Socket 程式設計

一文帶你瞭解Python Socket 程式設計

大家好,我是皮皮。

前言

Socket又稱為套接字,它是所有網路通訊的基礎。網路通訊其實就是程序間的通訊,Socket主要是使用IP地址,協議,埠號來標識一個程序。埠號的範圍為0~65535(使用者埠號一般大於1024),協議有很多種,一般我們經常用到的就是TCP,IP,UDP。下面我們來詳細瞭解下Socket吧。

一、匯入Socket模組

因為要操作套接字,所以需要用到套接字模組,系統中自帶的就很不錯,下面我們來匯入:

import socket

二、Socket基本用法

1.建立一個簡單的Socket連線

#建立Tcp/Ip套接字
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #流式Socket
#建立Udp/Ip套接字
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #資料報式Socket
socket.AF_UNIX  #只能夠用於單一的Unix系統程序間通訊
socket.AF_INET6  #只能夠用於IPv6通訊
socket.SOCK_RAW  #原始套接字,可以處理ICMP、ARP等網路報文,其它的不行
socket.SOCK_SEQPACKET  #可靠的連續資料包服務

2.協議對應埠

應用程式    FTP   TFTP  TELNET  SMTP  DNS   HTTP  SSH   MYSQL  POP3   MONGO
  埠     21,20  69     23     25    53    80    22    3306   110   27017
  協議      TCP   UDP    TCP    TCP   UDP   TCP   TCP    TCP   TCP    TCP

3.Socket函式

#建立Socket連線,比Connect更高階,可以自動解析不是數字的host地址,相容IPv4和 IPv6
socket.create_connection(address=('localhost',4320),timeout=4,source_address=('localhost',4320))  #前後兩個埠號一定要是一致,不然會報錯

#構建一對已連線的套接字物件,新建立的套接字都是不可繼承的
socket.socketpair(family=socket.AF_INET,type=socket.SOCK_STREAM,proto=0)

#從檔案描述符獲取到socket連線物件
socket.fromfd(fd=ab.fileno(),family=socket.AF_INET,type=socket.SOCK_STREAM,proto=0)

#套接字物件的型別
socket.SocketType

#返回套接字的5元組列表地址 ,支援IPV4/IPV6解析
socket.getaddrinfo(host='localhost',port=3453,family=socket.AF_INET,type=socket.SOCK_STREAM,proto=socket.IPPROTO_TCP,flags=0)
output:
[(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('127.0.0.1', 3453))]

#獲取主機名
socket.gethostname()
socket.getfqdn()
socket.getfqdn(socket.gethostname())

#將主機名轉化為IP地址
socket.gethostbyname('www.baidu.com') #不支援IPV6解析
socket.gethostbyname_ex('www.baidu.com') #返回三元組,(主機名,相同地址的其它可用主機名的列表,IPv4 地址列表)

#網路ip地址
socket.gethostbyname(socket.getfqdn(socket.gethostname()))

#將ip地址轉化為主機名,返回三元組(主機名,相同地址的其它可用主機名的列表,IPv4地址列表),支援IPV4/IPV6
socket.gethostbyaddr('192.168.1.4')

#解析主機名或者IP地址
socket.getnameinfo(('192.168.1.4',5434),0)

#判斷是否支援IPV6
socket.has_ipv6

#返回服務所使用的埠號
socket.getservbyname('https','tcp') #第一個引數為服務協議:Https,Http;第二個為傳輸協議:Tcp Udp

#返回埠所對應的服務
socket.getservbyport(443,'tcp')

#設定主機名(僅限於Unix)
socket.sethostname(name)

#返回網絡卡資訊的列表(僅限於Unix)
socket.if_nameindex()

#32位位元組儲存Ip地址(序列化)
socket.inet_aton('127.0.0.1')

#將32位位元組轉化為Ip地址(反序列化)
socket.inet_ntoa(b'\x7f\x00\x00\x01')

4.套接字函式

1).伺服器端函式

s.bind((host,port)) #將地址繫結到套接字,以(host,port)的元祖形式
s.listen(num)  #建立最多num個連線,最好別太大
s.accept()     #等待並接受客戶端的連線,返回新的套接字物件和(host,port)元祖

2).客戶端函式

s.connect((host,port)) #建立與伺服器的連線,以(host,port)的元祖形式
s.connect_ex((host,port)) #和上面的功能差不多,只是出錯了不拋異常,只是返回出錯碼

3).通用函式


s.recv(size,flag)       #接收最多size個大小的資料,flag可以忽略,返回值為資料是字串形式
s.send(str,flag)        #傳送str資料,返回值是要傳送的位元組數量,可能資料未全部發送
s.sendall(str,flag)     #傳送全部str資料,成功返回None,失敗則丟擲異常
s.recv(size,flag)       #接受最多size個數據,並以字串形式返回
s.recvfrom(str,flag)    #與recv相同,但是返回值是(接收資料的字串,傳送資料的套接字地址)的元祖形式
s.sendto(str,flag,address) #連線到當前套接字的遠端地址。返回值是傳送的位元組數,主要用於UDP
s.getpeername()     #返回連線套接字的遠端地址。返回值通常是元組(host,port)
s.getsockname()     #返回套接字自己的地址。通常是一個元組(host,port)
s.setsockopt(level,optname,value) # 設定給定套接字選項的值。
#假如埠被socket使用過,並且利用socket.close()來關閉連線,但此時埠還沒有釋放,要經過TIME_WAIT的過程之後才能使用;為了實現埠的馬上覆用,可以選擇setsocket()函式來達到目的。
#level:選項定義的層次。支援SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。
#optname:需設定的選項。SO_REUSEADDR SO_REUSEPORT
#value:設定選項的值。
s.getsockopt(level,optname,buflen) #返回套接字選項的值。buflen:快取長度
s.settimeout(time)  #設定socket連線超時時間,單位為秒,超時一般在剛建立套接字時設定
s.gettimeout()      #返回當前超時的時間,單位是秒,如果沒有設定超時,則返回None。
s.close()           #關閉套接字
s.fileno()          #套接字的檔案描述符
s.shutdown(how)     # 關閉連線一邊或兩邊
s.setblocking(bool) #是否阻塞(預設True),如果設定False,那麼accept和recv時一旦無資料,則報錯。
s.makefile()        #建立一個與該套接字相關聯的檔案

5.一個簡單的客戶端與服務端互動

Server.py

import socket 
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)             # 建立socket物件
s.bind(('127.0.0.1',4323))                                      # 繫結地址
s.listen(5)                                                     # 建立5個監聽
while True:
    conn,addr= s.accept()                                       # 等待客戶端連線
    print('歡迎{}'.format(addr))                              #列印訪問的使用者資訊
    while True:
        data=conn.recv(1024) 
        dt=data.decode('utf-8')                                 #接收一個1024位元組的資料 
        print('收到:',dt)
        aa=input('伺服器發出:') 
        if aa=='quit':
            conn.close()                                        #關閉來自客戶端的連線
            s.close()                                           #關閉伺服器端連線
        else:
            conn.send(aa.encode('utf-8'))

Client.py


import socket   
import sys
c=socket.socket()                                           # 建立socket物件
c.connect(('127.0.0.1',4323))                                #建立連線
while True:
    ab=input('客戶端發出:')
    if ab=='quit':
        c.close()                                               #關閉客戶端連線
        sys.exit(0)
    else:
        c.send(ab.encode('utf-8'))                               #傳送資料
        data=c.recv(1024)                                        #接收一個1024位元組的資料
        print('收到:',data.decode('utf-8'))     

可以看到我們實現了一個全雙工的Tcp/Ip聊天工具,對於伺服器和客戶端來說,均可收發檔案。

三、總結

Python中的socket程式設計難度不大,不過你要想寫好的Socket也不容易,希望本文能讓大家受益匪淺,畢竟小編可是把絕大多數經常用到的Api的功能都展示了。

小夥伴們,快快用實踐一下吧!如果在學習過程中,有遇到任何問題,歡迎加我好友,我拉你進Python學習交流群共同探討學習。