創(chuàng)新互聯(lián)建站于2013年開始,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站設(shè)計(jì)、做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元建湖做網(wǎng)站,已為上家服務(wù),為建湖各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220
---引入
Socket的英文原義是“孔”或“插座”,在Unix的進(jìn)程通信機(jī)制中又稱為‘套接字’。套接字實(shí)際上并不復(fù)雜,它是由一個(gè)ip地址以及一個(gè)端口號(hào)組成。Socket正如其英文原意那樣,像一個(gè)多孔插座。一臺(tái)主機(jī)猶如布滿各種插座(ip地址)的房間,每個(gè)插座有很多插口(端口),通過這些插口接入電線(進(jìn)程)我們可以燒水,看電視,玩電腦……
應(yīng)用程序通常通過"套接字"向網(wǎng)絡(luò)發(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求。
套接字的作用之一就是用來區(qū)分不同應(yīng)用進(jìn)程,當(dāng)某個(gè)進(jìn)程綁定了本機(jī)ip的某個(gè)端口,那么所有傳送至這個(gè)ip地址上的這個(gè)端口的所有數(shù)據(jù)都會(huì)被內(nèi)核送至該進(jìn)程進(jìn)行處理。
---python中的socket
Python 提供了兩個(gè)基本的 socket 模塊。
第一個(gè)是 Socket,它提供了標(biāo)準(zhǔn)的 BSD Sockets API。
第二個(gè)是 SocketServer, 它提供了服務(wù)器中心類,可以簡(jiǎn)化網(wǎng)絡(luò)服務(wù)器的開發(fā)。
----socket
先來說第一個(gè)。
我們知道,現(xiàn)在的應(yīng)用程序大多為C/S架構(gòu),也就是分為客戶端/服務(wù)器端。
服務(wù)器端:服務(wù)器端進(jìn)程需要申請(qǐng)?zhí)捉幼郑缓笞约航壎ㄔ谶@個(gè)套接字上,并對(duì)這個(gè)套接字進(jìn)行監(jiān)聽。當(dāng)有客戶端發(fā)送數(shù)據(jù)了,則接受數(shù)據(jù)進(jìn)行處理,處理完成后對(duì)客戶端進(jìn)行響應(yīng)。
客戶端:客戶端則相對(duì)簡(jiǎn)單些,客戶端只需要申請(qǐng)一個(gè)套接字,然后通過這個(gè)套接字連接服務(wù)器端的套接字,連接建立后就可以進(jìn)行后續(xù)操作了。
python編寫服務(wù)器端的步驟:
1 創(chuàng)建套接字
=
2 綁定套接字
s1.bind( address )#由AF_INET所創(chuàng)建的套接字,address地址必須是一個(gè)雙元素元組,格式是(host,port)。host代表主機(jī),port代表端口號(hào)。
#如果端口號(hào)正在使用、主機(jī)名不正確或端口已被保留,bind方法將引發(fā)socket.error異常。#例: ('192.168.1.1',9999)
3 監(jiān)聽套接字
s1.listen( backlog ) #backlog指定最多允許多少個(gè)客戶連接到服務(wù)器。它的值至少為1。收到連接請(qǐng)求后,這些請(qǐng)求需要排隊(duì),如果隊(duì)列滿,就拒絕請(qǐng)求。
4 等待接受連接
connection, address = s1.accept()#調(diào)用accept方法時(shí),socket會(huì)時(shí)入“waiting”狀態(tài),也就是處于阻塞狀態(tài)。客戶請(qǐng)求連接時(shí),方法建立連接并返回服務(wù)器。#accept方法返回一個(gè)含有兩個(gè)元素的元組(connection,address)。 #第一個(gè)元素connection是所連接的客戶端的socket對(duì)象(實(shí)際上是該對(duì)象的內(nèi)存地址),服務(wù)器必須通過它與客戶端通信; #第二個(gè)元素 address是客戶的Internet地址。
5 處理階段
connection.recv(bufsize[,flag])
#注意此處為connection#接受套接字的數(shù)據(jù)。數(shù)據(jù)以字符串形式返回,bufsize指定最多可以接收的數(shù)量。flag提供有關(guān)消息的其他信息,通常可以忽略connection.send(string[,flag])#將string中的數(shù)據(jù)發(fā)送到連接的套接字。返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于string的字節(jié)大小。即:可能未將指定內(nèi)容全部發(fā)送。
6 傳輸結(jié)束,關(guān)閉連接
s1.close()#關(guān)閉套接字
python編寫客戶端
1 創(chuàng)建socket對(duì)象
import socket s2=socket.socket()
2 連接至服務(wù)器端
s2.connect(address)#連接到address處的套接字。一般,address的格式為元組(hostname,port),如果連接出錯(cuò),返回socket.error錯(cuò)誤。
3 處理階段
s2.recv(bufsize[,flag])#接受套接字的數(shù)據(jù)。數(shù)據(jù)以字符串形式返回,bufsize指定最多可以接收的數(shù)量。flag提供有關(guān)消息的其他信息,通常可以忽略s2.send(string[,flag])#將string中的數(shù)據(jù)發(fā)送到連接的套接字。返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于string的字節(jié)大小。即:可能未將指定內(nèi)容全部發(fā)送。
4 連接結(jié)束,關(guān)閉套接字
s2.close()
socket中還有許多方法 :
socket.getaddrinfo(host, port, family=0, type=0, proto=0, flags=0) 10061=0, count=
好了,介紹完socket現(xiàn)在該介紹socketserver了。
----socketserver
雖說用Python編寫簡(jiǎn)單的網(wǎng)絡(luò)程序很方便,但復(fù)雜一點(diǎn)的網(wǎng)絡(luò)程序還是用現(xiàn)成的框架比較 好。這樣就可以專心事務(wù)邏輯,而不是套接字的各種細(xì)節(jié)。SocketServer模塊簡(jiǎn)化了編寫網(wǎng)絡(luò)服務(wù)程序的任務(wù)。同時(shí)SocketServer模塊也 是Python標(biāo)準(zhǔn)庫(kù)中很多服務(wù)器框架的基礎(chǔ)。
socketserver在python2中為SocketServer,在python3種取消了首字母大寫,改名為socketserver。
socketserver中包含了兩種類,一種為服務(wù)類(server class),一種為請(qǐng)求處理類(request handle class)。前者提供了許多方法:像綁定,監(jiān)聽,運(yùn)行…… (也就是建立連接的過程) 后者則專注于如何處理用戶所發(fā)送的數(shù)據(jù)(也就是事務(wù)邏輯)。
一般情況下,所有的服務(wù),都是先建立連接,也就是建立一個(gè)服務(wù)類的實(shí)例,然后開始處理用戶請(qǐng)求,也就是建立一個(gè)請(qǐng)求處理類的實(shí)例。
我們分析一下源碼,來看一看服務(wù)類是如何與請(qǐng)求處理類建立聯(lián)系的。
== = = ===
我們接下來介紹一下這兩個(gè)類
先來看服務(wù)類:
5種類型:BaseServer,TCPServer,UnixStreamServer,UDPServer,UnixDatagramServer。
BaseServer不直接對(duì)外服務(wù)。
TCPServer針對(duì)TCP套接字流
UDPServer針對(duì)UDP數(shù)據(jù)報(bào)套接字
UnixStreamServer和UnixDatagramServer針對(duì)UNIX域套接字,不常用。
他們之間的繼承關(guān)系:
服務(wù)類的方法:
View Code
這個(gè)幾個(gè)服務(wù)類都是同步處理請(qǐng)求的:一個(gè)請(qǐng)求沒處理完不能處理下一個(gè)請(qǐng)求。要想支持異步模型,可以利用多繼承讓server類繼承ForkingMixIn 或 ThreadingMixIn mix-in classes。
ForkingMixIn利用多進(jìn)程(分叉)實(shí)現(xiàn)異步。
ThreadingMixIn利用多線程實(shí)現(xiàn)異步。
請(qǐng)求處理器類:
要實(shí)現(xiàn)一項(xiàng)服務(wù),還必須派生一個(gè)handler class請(qǐng)求處理類,并重寫父類的handle()方法。handle方法就是用來專門是處理請(qǐng)求的。該模塊是通過服務(wù)類和請(qǐng)求處理類組合來處理請(qǐng)求的。
SocketServer模塊提供的請(qǐng)求處理類有BaseRequestHandler,以及它的派生類StreamRequestHandler和DatagramRequestHandler。從名字看出可以一個(gè)處理流式套接字,一個(gè)處理數(shù)據(jù)報(bào)套接字。
請(qǐng)求處理類有三種方法:
setup
()
Called before the handle()
method to perform any initialization actions required. The default implementation does nothing.
也就是在handle()之前被調(diào)用,主要的作用就是執(zhí)行處理請(qǐng)求之前的初始化相關(guān)的各種工作。默認(rèn)不會(huì)做任何事。(如果想要讓其做一些事的話,就要程序員在自己的請(qǐng)求處理器中覆蓋這個(gè)方法(因?yàn)橐话阕远x的請(qǐng)求處理器都要繼承python中提供的BaseRequestHandler,ps:下文會(huì)提到的),然后往里面添加?xùn)|西即可)
handle
()
This function must do all the work required to service a request. The default implementation does nothing. Several instance attributes are available to it; the request is available as self.request
; the client address as self.client_address
; and the server instance as self.server
, in case it needs access to per-server information.
The type of self.request
is different for datagram or stream services. For stream services,self.request
is a socket object; for datagram services, self.request
is a pair of string and socket.
handle()的工作就是做那些所有與處理請(qǐng)求相關(guān)的工作。默認(rèn)也不會(huì)做任何事。他有數(shù)個(gè)實(shí)例參數(shù):self.request self.client_address self.server
finish
()
Called after the handle()
method to perform any clean-up actions required. The default implementation does nothing. If setup()
raises an exception, this function will not be called.
在handle()方法之后會(huì)被調(diào)用,他的作用就是執(zhí)行當(dāng)處理完請(qǐng)求后的清理工作,默認(rèn)不會(huì)做任何事
Handler源碼
從源碼中可以看出,BaseRequestHandler中的setup()/handle()/finish()什么內(nèi)容都沒有定義,而他的兩個(gè)派生類StreamRequestHandler和DatagramRequestHandler則都重寫了setup()/finish()。
因此當(dāng)我們需要自己編寫socketserver程序時(shí),只需要合理選擇StreamRequestHandler和DatagramRequestHandler之中的一個(gè)作為父類,然后自定義一個(gè)請(qǐng)求處理類,并在其中重寫handle()方法即可。
用socketserver創(chuàng)建一個(gè)服務(wù)的步驟:
1 創(chuàng)建一個(gè)request handler class(請(qǐng)求處理類),合理選擇StreamRequestHandler和DatagramRequestHandler之中的一個(gè)作為父類(當(dāng)然,使用BaseRequestHandler作為父類也可),并重寫它的handle()方法。
2 實(shí)例化一個(gè)server class對(duì)象,并將服務(wù)的地址和之前創(chuàng)建的request handler class傳遞給它。
3 調(diào)用server class對(duì)象的handle_request() 或 serve_forever()方法來開始處理請(qǐng)求。
當(dāng)前標(biāo)題:python基礎(chǔ)之socket與socketserver
URL分享:http://vcdvsql.cn/article33/gjcess.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司、做網(wǎng)站、定制開發(fā)、企業(yè)建站、外貿(mào)建站、品牌網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)