1. 程式人生 > 實用技巧 >python之socket程式設計

python之socket程式設計

python之socket程式設計

本章內容

  1、socket

  2、IO多路複用

  3、socketserver

Socket

socket起源於Unix,而Unix/Linux基本哲學之一就是“一切皆檔案”,對於檔案用【開啟】【讀寫】【關閉】模式來操作。socket就是該模式的一個實現,socket即是一種特殊的檔案,一些socket函式就是對其進行的操作(讀/寫IO、開啟、關閉)

基本上,Socket 是任何一種計算機網路通訊中最基礎的內容。例如當你在瀏覽器位址列中輸入 http://www.cnblogs.com/時,你會開啟一個套接字,然後連線到 http://www.cnblogs.com/並讀取響應的頁面然後然後顯示出來。而其他一些聊天客戶端如 gtalk 和 skype 也是類似。任何網路通訊都是通過 Socket 來完成的。

Python 官方關於 Socket 的函式請看http://docs.python.org/library/socket.html

socket和file的區別:

  1、file模組是針對某個指定檔案進行【開啟】【讀寫】【關閉】

  2、socket模組是針對 伺服器端 和 客戶端Socket 進行【開啟】【讀寫】【關閉】

那我們就先來建立一個socket服務端吧

server View Code

socket更多功能

更多功能

注:擼主知道大家懶,所以把全部功能的中文標記在每個功能的下面啦。下面擼主列一些經常用到的吧

sk.bind(address)

  s.bind(address) 將套接字繫結到地址。address地址的格式取決於地址族。在AF_INET下,以元組(host,port)的形式表示地址。

sk.listen(backlog)

  開始監聽傳入連線。backlog指定在拒絕連線之前,可以掛起的最大連線數量。

backlog等於5,表示核心已經接到了連線請求,但伺服器還沒有呼叫accept進行處理的連線個數最大為5
這個值不能無限大,因為要在核心中維護連線佇列

sk.setblocking(bool)

  是否阻塞(預設True),如果設定False,那麼accept和recv時一旦無資料,則報錯。

sk.accept()

  接受連線並返回(conn,address),其中conn是新的套接字物件,可以用來接收和傳送資料。address是連線客戶端的地址。

  接收TCP 客戶的連線(阻塞式)等待連線的到來

sk.connect(address)

  連線到address處的套接字。一般,address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。

sk.connect_ex(address)

  同上,只不過會有返回值,連線成功時返回 0 ,連線失敗時候返回編碼,例如:10061

sk.close()

  關閉套接字

sk.recv(bufsize[,flag])

  接受套接字的資料。資料以字串形式返回,bufsize指定最多可以接收的數量。flag提供有關訊息的其他資訊,通常可以忽略。

sk.recvfrom(bufsize[.flag])

  與recv()類似,但返回值是(data,address)。其中data是包含接收資料的字串,address是傳送資料的套接字地址。

sk.send(string[,flag])

  將string中的資料傳送到連線的套接字。返回值是要傳送的位元組數量,該數量可能小於string的位元組大小。即:可能未將指定內容全部發送。

sk.sendall(string[,flag])

  將string中的資料傳送到連線的套接字,但在返回之前會嘗試傳送所有資料。成功返回None,失敗則丟擲異常。

內部通過遞迴呼叫send,將所有內容傳送出去。

sk.sendto(string[,flag],address)

  將資料傳送到套接字,address是形式為(ipaddr,port)的元組,指定遠端地址。返回值是傳送的位元組數。該函式主要用於UDP協議。

sk.settimeout(timeout)

  設定套接字操作的超時期,timeout是一個浮點數,單位是秒。值為None表示沒有超時期。一般,超時期應該在剛建立套接字時設定,因為它們可能用於連線的操作(如 client 連線最多等待5s )

sk.getpeername()

  返回連線套接字的遠端地址。返回值通常是元組(ipaddr,port)。

sk.getsockname()

  返回套接字自己的地址。通常是一個元組(ipaddr,port)

sk.fileno()

  套接字的檔案描述符

TCP:

案例一 機器人聊天 案例二 上傳檔案

UdP

udp傳輸

WEB服務應用:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #!/usr/bin/env python #coding:utf-8 importsocket defhandle_request(client): buf=client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n") client.send("Hello, World") defmain(): sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8080)) sock.listen(5) whileTrue: connection, address=sock.accept() handle_request(connection) connection.close() if__name__=='__main__': main()

IO多路複用

I/O(input/output),即輸入/輸出埠。每個裝置都會有一個專用的I/O地址,用來處理自己的輸入輸出資訊首先什麼是I/O:

I/O分為磁碟io和網路io,這裡說的是網路io

IO多路複用:

I/O多路複用指:通過一種機制,可以監視多個描述符(socket),一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。

Linux

Linux中的 select,poll,epoll 都是IO多路複用的機制。

Linux下網路I/O使用socket套接字來通訊,普通I/O模型只能監聽一個socket,而I/O多路複用可同時監聽多個socket.

I/O多路複用避免阻塞在io上,原本為多程序或多執行緒來接收多個連線的訊息變為單程序或單執行緒儲存多個socket的狀態後輪詢處理.

Python

Python中有一個select模組,其中提供了:select、poll、epoll三個方法,分別呼叫系統的 select,poll,epoll 從而實現IO多路複用。

1 2 3 4 5 6 7 8 9 10 11 Windows Python: 提供: select Mac Python: 提供: select Linux Python: 提供: select、poll、epoll

對於select模組操作的方法:

1 2 3 4 5 6 7 8 9 10 11 控制代碼列表11, 控制代碼列表22, 控制代碼列表33=select.select(控制代碼序列1, 控制代碼序列2, 控制代碼序列3, 超時時間) 引數: 可接受四個引數(前三個必須) 返回值:三個列表 select方法用來監視檔案控制代碼,如果控制代碼發生變化,則獲取該控制代碼。 1、當 引數1序列中的控制代碼發生可讀時(accetp和read),則獲取發生變化的控制代碼並新增到 返回值1序列中 2、當 引數2序列中含有控制代碼時,則將該序列中所有的控制代碼新增到 返回值2序列中 3、當 引數3序列中的控制代碼發生錯誤時,則將該發生錯誤的控制代碼新增到 返回值3序列中 4、當 超時時間 未設定,則select會一直阻塞,直到監聽的控制代碼發生變化 5、當 超時時間 =1時,那麼如果監聽的控制代碼均無任何變化,則select會阻塞1秒,之後返回三個空列表,如果監聽的控制代碼有變化,則直接執行。
利用select監聽終端操作例項 利用select實現偽同時處理多個Socket客戶端請求 利用select實現偽同時處理多個Socket客戶端請求讀寫分離

socketserver

SocketServer內部使用 IO多路複用 以及 “多執行緒” 和 “多程序” ,從而實現併發處理多個客戶端請求的Socket服務端。即:每個客戶端請求連線到伺服器時,Socket服務端都會在伺服器是建立一個“執行緒”或者“程序” 專門負責處理當前客戶端的所有請求。

ThreadingTCPServer

ThreadingTCPServer實現的Soket伺服器內部會為每個client建立一個 “執行緒”,該執行緒用來和客戶端進行互動。

1、ThreadingTCPServer基礎

使用ThreadingTCPServer:

  • 建立一個繼承自 SocketServer.BaseRequestHandler 的類
  • 類中必須定義一個名稱為 handle 的方法
  • 啟動ThreadingTCPServer
服務端 客戶端

2、ThreadingTCPServer原始碼剖析

ThreadingTCPServer的類圖關係如下:

內部呼叫流程為:

  • 啟動服務端程式
  • 執行 TCPServer.__init__ 方法,建立服務端Socket物件並繫結 IP 和 埠
  • 執行 BaseServer.__init__ 方法,將自定義的繼承自SocketServer.BaseRequestHandler 的類 MyRequestHandle賦值給self.RequestHandlerClass
  • 執行 BaseServer.server_forever 方法,While 迴圈一直監聽是否有客戶端請求到達 ...
  • 當客戶端連線到達伺服器
  • 執行 ThreadingMixIn.process_request 方法,建立一個 “執行緒” 用來處理請求
  • 執行ThreadingMixIn.process_request_thread 方法
  • 執行 BaseServer.finish_request 方法,執行self.RequestHandlerClass() 即:執行 自定義 MyRequestHandler 的構造方法(自動呼叫基類BaseRequestHandler的構造方法,在該構造方法中又會呼叫 MyRequestHandler的handle方法)

相對應的原始碼如下:

Baseserver TCP server ThreadingMixIn SocketServer.BaseRequestHandler

SocketServer的ThreadingTCPServer之所以可以同時處理請求得益於select和Threading兩個東西,其實本質上就是在伺服器端為每一個客戶端建立一個執行緒,當前執行緒用來處理對應客戶端的請求,所以,可以支援同時n個客戶端連結(長連線)。