2015/12/14 Python網絡編程,TCP/IP客戶端和服務器初探

一直不是很清楚服務器的定義,對於什麼是服務器/客戶端架構也只有一個模糊的感受。最近開始學習,才明白一些什麼服務器和客戶端的關係。數據庫

所謂的服務器,就是提供服務的東西,它是一個硬件或者軟件,能夠向一個或者多個客戶端提供所須要的服務。它存在的目的就是等待客戶的請求,而後給客戶服務,再接着等待請求。編程

而客戶端,就來連上一個服務器,提出本身的請求,而後等待得到反饋。服務器

好比說,打印機就是一個服務器的例子,與之相連的計算機就是客戶端,經過網絡鏈接打印機後,給它提出服務需求(打印)和傳輸數據(傳輸內容),而後打印機開始工做,或者返回形成服務失敗的緣由(好比缺紙或者沒有墨)打印機是服務器端,它是一隻等待請求的,它在一直工做,計算機這端是客戶端,它不是一隻工做的。網絡

打印機是一個硬件服務器,也有一些軟件服務器,好比說Web服務器,數據庫服務器等等。數據結構

-----------------------------------------------------------------------------架構

那麼它們又是怎樣經過網絡鏈接的呢?客戶端/服務器之間的網絡編程是如何作的?框架

首先,咱們要建立一個通信的斷電,讓服務器能夠「監聽」請求,比如公司的電話,客戶經過電話設備向公司發行請求。socket

固然一個服務器在有電話以後還得將本身的電話給潛在的客戶,才能獲得響應,也就是說,必須得將網址發給客戶纔能有用。tcp

對於客戶端來講,一樣也是建立一個通訊端點,而後創建到與服務器的鏈接,客戶就能夠提出請求了。函數

-------------------------------------------------------------------------------------

關於通信端點,就要介紹一個概念,叫套接字。

咱們以前談的「通信端點」的概念,是一個關於通信的抽象,而套接字就是一種有這樣能力數據結構了。

就比如咱們應用整型浮點型布爾型同樣,套接字也是一種數據結構,咱們經過它來訪問網絡。

套接字起源於上世紀七十年代,在加州大學伯克利分校版本上的Unix上創立,開始的時候被設計用於在同一臺機器上的多個應用程序通信,也就是進程間通信,有兩種類型,一種基於文件系統,一種基於網絡。

基於文件系統被用於不一樣進程通信是頗有意義的,由於文件系統是不一樣的進程均可以訪問的。而不一樣電腦間,基於網絡的套接字就是必須的了。

我先只考慮基於網絡的套接字,有兩種地址家族,一種是AF_INET,另外一種是AF_NETLINK。在大部分時候,咱們討論的都是有連接的AF_INET套接字。

 

套接字的地址是有兩部分組成的,一個是主機,一個是端口。

相似於電話網絡的區號和電話號碼的含義。主機肯定了你訪問的機器,也就是一個IP地址,端口是你所訪問的服務器軟件所使用的端口號。一臺機器上能夠有不少個程序都在使用端口,合法的端口號範圍是0~65535.小於1024的端口號是系統保留的端口號。

-------------------------------------------------------------------------------------

同時,還有一個基礎知識是面向鏈接和麪向無鏈接。

套接字有兩種類型,一種是面向鏈接的,通訊前先創建一條鏈接,而後順序的、可靠的、不會重複的數據傳輸,不會有數據邊界。實現這種鏈接的主要協議是傳輸控制協議(TCP),建立TCP套接字要指定套接字類型是SOCK_STREAM.

另外一種是無鏈接套接字,也就是說傳輸數據前先不鏈接,這樣數據傳輸的順序、可靠性、不重複性就不可保證。這種傳輸的主要協議是用戶數據報協議(UDP)。

----------------------------------------------------------------------------------------------

至此,網絡的基礎暫且放下,開始講Python的網絡編程。

Python提供了一個socket模塊,來建立和使用套接字。

 

socket()模塊函數

socket(socket_family, socket_type, protocol=0)

這個函數能夠用於建立一個套接字對象,分別寫入套接字家族名和套接字類型。

建立了這個套接字對象後,全部的交互均可以經過該對象的方法調用來進行。

具體的方法能夠直接查Python的文檔,我這裏舉例說明一下建立一個TCP服務器的過程:

from socket import *
from time import ctime

HOST = ''  # 主機
PORT = 8002 # 端口號,能夠隨意選擇
BUFSIZ = 1024
ADDR = (HOST, PORT) #主機端口號組成一個套接字地址

tcpSerSock = socket(AF_INET, SOCK_STREAM) #建立一個套接字對象,是AF_INET族的tcp套接字
tcpSerSock.bind(ADDR) #這個函數用於綁定地址到套接字
tcpSerSock.listen(5) # 服務器開始監聽鏈接,參數表示最多容許同時有幾個鏈接進來

while True:
    print 'waiting for connection...'
    tcpCliSock, addr = tcpSerSock.accept() #用於等待鏈接的到來
    print '...connected from:',addr

    while True:
        data = tcpCliSock.recv(BUFSIZ) #用於接收從客戶端發來的數據 參數表明一次最多接受的數據量,這裏爲1k
        if not data:
            break
        tcpCliSock.send('[%s] %s' % (
            ctime(), data)) # 將時間戳做爲內容發送給客戶端

    tcpCliSock.close()

tcpSerSock.close()

運行時,能夠看到服務器開始運行,等待一個客戶端的鏈接,因此此刻咱們須要用客戶端去鏈接這個服務器。

再寫一個簡單的客戶端的程序:

from socket import *

HOST = 'localhost' #因爲服務器開設在本身電腦上,因此主機是本地
PORT = 8002 #同一個鏈接端口
BUFSIZ = 1024
ADDR = (HOST, PORT)

tcpCliSock = socket(AF_INET, SOCK_STREAM) #一樣的TCP套接字
tcpCliSock.connect(ADDR) # 鏈接相應的地址,初始化TCP服務器的鏈接

while True:
    data = raw_input('>')
    if not data:
        break
    tcpCliSock.send(data) # 向服務器傳輸數據
    data = tcpCliSock.recv(BUFSIZ) # 接受服務器端的數據
    if not data:
        break
    print data

tcpCliSock.close()

至此,你運行客戶端的程序,就能夠驗證程序了。

 


 

固然,爲了學習的樂趣,最好不要在本地鏈接,仍是拿兩臺電腦來鏈接比較好,主要是客戶端要知道服務器端的IP地址。

IP地址在網絡屬性裏能夠找,如圖:

而後用一樣的程序框架就能夠實現兩機間的通信了,最後能夠作到以下圖的一個對講機程序:

固然,要作到一個雙方均可以自由發言的聊天工具,卻又不是這麼簡單了。須要有新的嘗試了。

相關文章
相關標籤/搜索