python之我理解的socket

2022-07-30 05:27:15 字數 4740 閱讀 7803

一.為什麼學socket?

完成c/s架構的開發。

思考:什麼是c/s架構。

二.學前準備

計算機系統=硬體+系統軟體+應用軟體,將這樣的計算機比作成乙個人,在地球這樣的大環境下你只能和自己玩(比如自帶的單機遊戲掃雷什麼的),但是地球上不會就只有乙個人,地球上的人需要互相交流(語言),要想所有人都聽得懂所以人類出了乙個官方的語言英語,計算機之間交流就是通過網際網路協議。

重點:網際網路的核心就是由一堆協議組成,協議就是標準,比如全世界人通訊的標準是英語

為什麼學習socket要先學習網際網路協議?

1.首先:學習socket是為了開發c/s架構軟體

2.其次:c/s架構的軟體(軟體屬於應用層)是基於網路進行通訊的

3.最後:網路的核心即一堆協議,協議即標準,你想開發一款基於網路通訊的軟體,就必須遵循這些標準。

三.了解socket的位置

四.什麼是socket?

將socket理解為乙個袋子,這個袋子將應用層與下面的所有層分開,將下面的層整齊的封裝起來,袋子口上面有介面。我們不需要理解袋子裡裝的協議,只需要遵循socket的協議就可以。

五.套接字發展與分類

套接字起源於 20 世紀 70 年代加利福尼亞大學伯克利分校版本的 unix,即人們所說的 bsd unix。 因此,有時人們也把套接字稱為「伯克利套接字」或「bsd 套接字」。一開始,套接字被設計用在同 一台主機上多個應用程式之間的通訊。這也被稱程序間通訊,或 ipc。套接字有兩種(或者稱為有兩個種族),分別是基於檔案型的和基於網路型的。

基於檔案型別的套接字家族

套接字家族的名字:af_unix

unix一切皆檔案,基於檔案的套接字呼叫的就是底層的檔案系統來取資料,兩個套接字程序執行在同一機器,可以通過訪問同乙個檔案系統間接完成通訊

基於網路型別的套接字家族

套接字家族的名字:af_inet

(還有af_inet6被用於ipv6,還有一些其他的位址家族,不過,他們要麼是只用於某個平台,要麼就是已經被廢棄,或者是很少被使用,或者是根本沒有實現,所有位址家族中,af_inet是使用最廣泛的乙個,python支援很多種位址家族,但是由於我們只關心網路程式設計,所以大部分時候我麼只使用af_inet)。

六.套接字工作流程

乙個生活中的場景。你要打**給乙個朋友,先撥號,朋友聽到**鈴聲後提起**,這時你和你的朋友就建立起了連線,就可以講話了。等交流結束,結束通話**結束此次交談。生活中的場景就解釋了這工作原理。

先從伺服器端說起。

伺服器端先初始化socket(買乙個手機)。

然後與埠繫結(bind)(插上乙個**卡)。

對埠進行監聽(listen),

呼叫accept阻塞,等待客戶端連線。(等待朋友**)

客戶端在這時如果有個客戶端初始化乙個socket(朋友的**)。

然後連線伺服器(connect)(知道你的**號碼,給你打**)。

如果連線成功(接通**),這時客戶端與伺服器端的連線就建立了。

客戶端傳送資料請求,伺服器端接收請求並處理請求,然後把回應資料傳送給客戶端,客戶端讀取資料,最後關閉連線,一次互動結束

socket模組使用方法:

import socket------------------呼叫socket模組,來建立c/s架構

socket.socket(socket_family,socket_type,protocal=0)

socket_family 可以是 af_unix 或 af_inet。(選擇套接字家族,我們使用socket是為了服務端與客戶端之間的通訊,基於網路型別的所以選擇af_inet)

socket_type 可以是 sock_stream 或 sock_dgram。(選擇socket型別,傳輸有兩種tcp與udp,前者使用sock_stream,後者使用sock_dgram)

protocol 一般不填,預設值為 0。

獲取tcp/ip套接字

tcpsock = socket.socket(socket.af_inet, socket.sock_stream)

獲取udp/ip套接字

udpsock = socket.socket(socket.af_inet, socket.sock_dgram)

由於 socket 模組中有太多的屬性。我們在這裡破例使用了'from module import *'語句。使用 'from socket import *',我們就把 socket 模組裡的所有屬性都帶到我們的命名空間裡了,這樣能 大幅減短我們的**。

例如tcpsock = socket(af_inet, sock_stream)

服務端套接字函式s.bind()    繫結(主機,埠號)到套接字

s.listen() 開始tcp監聽

s.accept() 被動接受tcp客戶的連線,(阻塞式)等待連線的到來

客戶端套接字函式

s.connect() 主動初始化tcp伺服器連線

s.connect_ex() connect()函式的擴充套件版本,出錯時返回出錯碼,而不是丟擲異常

公共用途的套接字函式

s.recv() 接收tcp資料

s.send() 傳送tcp資料(send在待傳送資料量大於己端快取區剩餘空間時,資料丟失,不會發完)

s.sendall() 傳送完整的tcp資料(本質就是迴圈呼叫send,sendall在待傳送資料量大於己端快取區剩餘空間時,資料不丟失,迴圈呼叫send直到發完)

s.recvfrom() 接收udp資料

s.sendto() 傳送udp資料

s.getpeername() 連線到當前套接字的遠端的位址

s.getsockname() 當前套接字的位址

s.getsockopt() 返回指定套接字的引數

s.setsockopt() 設定指定套接字的引數

s.close() 關閉套接字

面向鎖的套接字方法

s.setblocking() 設定套接字的阻塞與非阻塞模式

s.settimeout() 設定阻塞套接字操作的超時時間

s.gettimeout() 得到阻塞套接字操作的超時時間

面向檔案的套接字的函式

s.fileno() 套接字的檔案描述符

s.makefile() 建立乙個與該套接字相關的檔案

七.基於tcp的socket

tcp是基於鏈結的,必須先啟動服務端,然後再啟動客戶端去鏈結服務端

tcp服務端

ss = socket() #

建立伺服器套接字

ss.bind() #

把位址繫結到套接字

ss.listen() #

監聽鏈結

inf_loop: #

伺服器無限迴圈

cs = ss.accept() #

接受客戶端鏈結

comm_loop: #

通訊迴圈

cs.recv()/cs.send() #

對話(接收與傳送)

cs.close() #

關閉客戶端套接字

ss.close() #

關閉伺服器套接字(可選)

tcp客戶端

cs = socket()    #

建立客戶套接字

cs.connect() #

嘗試連線伺服器

comm_loop: #

通訊迴圈

cs.send()/cs.recv() #

對話(傳送/接收)

cs.close() #

關閉客戶套接字

八.基於udp的socket

udp是無鏈結的,先啟動哪一端都不會報錯

udp服務端

1 ss = socket()   #建立乙個伺服器的套接字

2 ss.bind() #繫結伺服器套接字

3 inf_loop: #伺服器無限迴圈

4 cs = ss.recvfrom()/ss.sendto() # 對話(接收與傳送)

5 ss.close() # 關閉伺服器套接字

udp客戶端

cs = socket()   # 建立客戶套接字

comm_loop: # 通訊迴圈

cs.sendto()/cs.recvfrom() # 對話(傳送/接收)

cs.close() # 關閉客戶套接字

Python之我對閉包的理解2

1.儲存返回返回閉包時的狀態 外層函式值的狀態 def func a,b c 10def inner func 建立乙個內部函式就佔乙個位址,扔出來的是不會被 的 s a b c print 相加之後的結果是 s print locals return inner func 呼叫func func ...

Python之我對閉包理解1

閉包 針對函式而言,是在在函式中提出的概念 條件 1.外部函式中定義了內部函式 即有函式巢狀 2.外部函式有返回值 3.外部函式返回的值是 內部函式名 即函式入口位址 為方便記憶不搞混淆,我們這裡可以說返回的是函式名 4.內部函式呼叫 引用 了外部函式的變數 不引用不叫嚴格的閉包 格式 def 外部...

遞迴之我所理解

遞迴在實際程式設計中有著很重要的用處,最常見的用途莫過於檔案搜尋目錄遍歷了,我曾花了很長時間研究遞迴的性質,發現所有遞迴都可以用樹的結構描述出來,這只是我的發現,並沒有嚴格的證明,至少在我所研究過的所有遞迴應用例項中是成立的。遞迴的效率顯然不是很高,因為每次遞迴的時候,呼叫函式時得分配棧空間,函式返...