Python的網路程式設計(五)

2021-04-16 08:49:50 字數 2577 閱讀 1101

socket的阻塞或同步程式設計

一、使用socket

網 絡程式設計中最基本的部分就是socket(套接字)。socket有兩種:服務端socket和客戶端 socket。在你建立了乙個服務端socket之 後,你告訴它去等待連線。然後它將監聽某個網路位址(形如:***.***.***.***:***) 直到客戶端連線。然後這兩端就可以通訊了。

處理客戶端socket通常比處理服務端socket要容易一點,因為服務端必須時刻準備處理來自客戶端的連線,並且它必須處理多個連線,而客戶端只需要簡單的連線,然後做點什麼,然後斷開連線。

實 例化乙個socket時,可以指定三個引數:位址系列(預設為socket.af_inet)、流socket(這是個預設值:  socket.sock_stream)或資料報socket(socket.sock_dgram)、協議(預設值是0)。對於簡單的socket, 你可以不指定任何引數而全部使用預設值。

服務端socket在使用bind方法之後呼叫listen方法去監聽乙個給定的位址。然後,客 戶端socket就可以通過使用connect方法(connect方法所使用的位址引數與bind相同)去連線服務端。listen方法要求乙個引數, 這個引數就是等待連線佇列中所能包含的連線數。

一旦服務端socket呼叫了listen方法,就進入了臨聽狀態,然後通常使用乙個無限 的迴圈:1、開始接受客房端的連線,這通過呼叫accept方法來實現。呼叫了這個方法後將處於阻塞狀態(等待客戶端發起連線)直到乙個客戶端連線,連線 後,accept返回形如(client,address)的乙個元組,其中client是乙個用於與客戶端通訊的socket,address是客戶端 的形如***.***.***.***:***的位址;2、然後服務端處理客戶端的請求;3、處理完成之後又呼叫1。

關於傳輸資料,socket有兩個方法:send和recv。send使用字串引數傳送資料;recv引數是位元組數,表示一次接受的資料量,如果你不確定一次該接受的資料量的話,最好使用1024。

下面給出乙個最小的伺服器/客戶機的例子:

服務端:

import socket

s = socket.socket()

host = socket.gethostname()

port = 1234

s.bind((host, port))

s.listen(5)

while true:

c, addr = s.accept()

print 'got connection from', addr

c.send('thank you for connecting')

c.close()

客戶端:

import socket

s = socket.socket()

host = socket.gethostname()

port = 1234

s.connect((host, port))

print s.recv(1024)

注意:如果你使用ctrl-c來停止服務端的話,如果再次使用相同的埠可能需要等待一會兒。

二、使用socketserver

socketserver模組簡單化了編寫網路伺服器的工作。

它提供了四個基本的服務類:tcpserver(使用tcp協議)、udpserver(使用資料報)、unixstreamserver、

unixdatagramserver。unixstreamserver和unixdatagramserver用於類unix平台。

這四個類處理請求都使用同步的方法,也就是說,在下乙個請求處理開始之前當前的請求處理必須已完成

。 用socketserver建立乙個伺服器需要四步:

1、通過子類化baserequesthandler類和覆蓋它的handle()方法來建立乙個請求處理器類,用於處理進來

的請求;

3、呼叫服務例項物件的handle_request()或serve_forever()方法去處理請求。

下面使用socketserver用同步的方法寫乙個最簡單的伺服器:

from socketserver import tcpserver, streamrequesthandler

#第一步。其中streamrequesthandler類是baserequesthandler類的子類,它為流socket定義了

#rfile和wfile方法

class handler(streamrequesthandler):

def handle(self):

addr = self.request.getpeername()

print 'got connection from', addr

self.wfile.write('thank you for connecting')

#第二步。其中''代表執行伺服器的主機

server = tcpserver(('', 1234), handler)

#第三步。serve_forever()導致進入迴圈狀態

server.serve_forever()

TCP IP 網路程式設計(五)

select並不是把發生變化的檔案描述符單獨集中到一起,而是通過觀察作為監視物件的fd set函式的變化,因此不能避免對所有監視物件的迴圈語句。而且,監視物件變數會發生變化,在呼叫select函式之前要複製並儲存原有資訊,並在每次呼叫時傳遞新的監視物件資訊。傳遞新的監視物件資訊是資源消耗的主要原因,...

Linux網路程式設計(五)

linux伺服器模型。udp伺服器通常採用迴圈伺服器模型,tcp伺服器通常採用併發伺服器模型 實現思路 伺服器建立偵聽socket,並建立子程序。所有子程序呼叫accept,無連線時將睡眠。有連線到來時所有子程序被喚醒。某乙個子程序接受連線後,其他程序繼續睡眠。乙個預先建立子程序的例子。create...

網路程式設計(五) SIGPIPE

sigpipe訊號產生的原因 簡單來說,就是客戶端程式向伺服器端程式傳送了訊息,然後關閉客戶端,伺服器端返回訊息的時候就會收到核心給的sigpipe訊號。tcp的全雙工通道其實是兩條單工通道,client端呼叫close的時候,雖然本意是關閉兩條通道,但是其實只能關閉它傳送的那一條單工通道,還是可以...