天天看點

【Python之旅】第五篇(一):Python Socket通信原理

1.Socket

    socket也稱作“套接字”,用于描述IP位址和端口,是一個通信鍊的句柄。應用程式通常通過“套接字”向網絡送出請求或者應答網絡請求。可以列舉中國移動或者是中國電信等的電話客服,當然,也可以看下面的圖檔來作形象的說明。

    socket起源于Unix,而Unix/Linux基本哲學之一就是:一切皆檔案,即都可以用“打開open—>讀寫write/read—>關閉close”模式來操作。Socket就是該模式的一個實作,socket即是一種特殊的檔案,一些socket函數就是對其進行的操作(讀/寫IO、打開、關閉)。

    可以看下面的圖示來形象說明:

<a href="http://s3.51cto.com/wyfs02/M02/74/07/wKioL1YPYV-ASBXxAAG4ZzVVxxg286.jpg" target="_blank"></a>

2.Socket程式設計

(1)Socket伺服器程式設計

    主要包括下面的幾步:

1.打開socket

2.綁定到一個位址和端口

3.偵聽進來的連接配接

4.接受連接配接

5.讀寫資料

(2)Socket用戶端程式設計

2.連接配接到一個位址和端口

3.讀寫資料

3.Socket類型

    Socket從類型上分,可以有以下幾種:

socket類型

适用範圍

說明

socket.AF_UNIX

隻能夠用于單一的Unix系統程序間通信

不能在不同主機之間通信

socket.AF_INET

伺服器之間網絡通信

目前常用的就是這種

socket.AF_INET6

IPv6

由于IPv6未推廣,也少用

    上面是socket的類型,細分的話還有socket的資料包類型,圖示如下:

<a href="http://s3.51cto.com/wyfs02/M00/74/09/wKiom1YPZeHgW_wqAAHUjUnzsUk309.jpg" target="_blank"></a>

    常用的是第一種和第二種,即for TCP和for UDP的類型,當然socket.SOCK_RAW也需要注意,因為它可以構造IP頭,是以沿着這個思路,可以合僞造不同源IP位址的資料包,以對一些中小型企業伺服器發動Dos攻擊。

4.Socket函數

    對socket進行相關操作如“讀/寫IO、打開、關閉”的函數即是Socket函數,可以看下面的圖示:

5.Socket例子

    下面就寫一個單線程非互動式的socket,在本機裡實作通信就好了。

Server端:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

<code>import</code> <code>socket                #導入socket類</code>

<code>HOST =</code><code>''</code>                     <code>#定義偵聽本地位址口(多個IP位址情況下),這裡表示偵聽所有,也可以寫成</code><code>0.0</code><code>.</code><code>0.0</code>

<code>PORT = </code><code>50007</code>                 <code>#Server端開放的服務端口</code>

<code>s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    #選擇Socket類型和Socket資料包類型</code>

<code>s.bind((HOST, PORT))         #綁定IP位址和端口</code>

<code>s.listen(</code><code>1</code><code>)                  #定義偵聽數開始偵聽(實際上并沒有效果)</code>

<code>conn, addr = s.accept()      #定義執行個體,accept()函數的傳回值可以看上面的socket函數說明</code>

<code>print </code><code>'Connected by'</code><code>, addr</code>

<code>while</code> <code>1</code><code>:</code>

<code>    </code><code>data = conn.recv(</code><code>1024</code><code>)    #接受套接字的資料</code>

<code>    </code><code>if</code> <code>not data:</code><code>break</code>         <code>#如果沒有資料接收,則斷開連接配接</code>

<code>    </code><code>print </code><code>'revc:'</code><code>,data        #發送接收到的資料</code>

<code>    </code><code>conn.sendall(data)        #發送接收到的資料</code>

<code>conn.close()                      #關閉套接字</code>

Client端:

<code>import</code> <code>socket</code>

<code>HOST = </code><code>'192.168.1.13'</code>        <code>#定義目标主機名</code>

<code>PORT = </code><code>50007</code>                 <code>#定義目标主機開放服務端口号</code>

<code>s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #選擇Socket類型和Socket資料包類型 </code>

<code>s.connect((HOST, PORT))      #連接配接到目标主機的socket(套接字)中</code>

<code>s.sendall(</code><code>'Hello, world!'</code><code>)   #發送資料</code>

<code>data = s.recv(</code><code>1024</code><code>)          #接收資料</code>

<code>s.close()                    #關閉socket</code>

<code>print </code><code>'Received'</code><code>, repr(data)</code>

示範:

步驟1:Server端運作服務端程式

<code>xpleaf@xpleaf-machine:/mnt/hgfs/Python/day5$ python server4.py </code>

<code>===&gt;光标在此處處于等待狀态</code>

步驟2:Client端運作用戶端程式

<code>xpleaf@xpleaf-machine:/mnt/hgfs/Python/day5$ python client4.py </code>

<code>Received 'Hello, world!    ===&gt;收到服務端傳回的資料</code>

步驟3:在Server端中觀察現象

<code>Connected by (</code><code>'192.168.1.13'</code><code>, </code><code>52641</code><code>)    ===&gt;有用戶端連接配接進來,</code><code>52641</code><code>為Client的随機端口号</code>

<code>revc: Hello, world!                     ===&gt;收到來自Client端的資料</code>

本文轉自 xpleaf 51CTO部落格,原文連結:http://blog.51cto.com/xpleaf/1700032,如需轉載請自行聯系原作者