socket编程初级
什么是socket
定義
socket通常也稱作套接字,用于描述IP地址和端口,是一個通信鏈的句柄,應(yīng)用程序通常通過套接字向網(wǎng)絡(luò)發(fā)出請求或者應(yīng)答網(wǎng)絡(luò)請求。
socket起源于Unix,而Unix/Linux基本哲學(xué)之一就是“一切皆文件”,對于文件用【打開】【讀寫】【關(guān)閉】模式來操作。socket就是該模式的一個實現(xiàn),socket即是一種特殊的文件,一些socket函數(shù)就是對其進行的操作(讀/寫IO、打開、關(guān)閉)
socket和file的區(qū)別:
file模塊是針對某個指定文件進行【打開】【讀寫】【關(guān)閉】
socket模塊是針對 服務(wù)器端 和 客戶端Socket 進行【打開】【讀寫】【關(guān)閉】
python相關(guān)
Python 提供了兩個基本的 socket 模塊。py2位大寫,py3全部小寫
第一個是 Socket,它提供了標(biāo)準的 BSD Sockets API。
第二個是 SocketServer, 它提供了服務(wù)器中心類,可以簡化網(wǎng)絡(luò)服務(wù)器的開發(fā)
socket編程實現(xiàn)
流程圖:
說明:
服務(wù)端
1.服務(wù)端需要導(dǎo)入socket模塊,并創(chuàng)建套接字(實例化為一個對象)
import?socket s?=?socket.socket()?
2.綁定套接字s到本地IP和端口
ip_port?=?('127.0.0.1',8080) s.bind(ip_port)?
3.監(jiān)聽連接
s.listen(0)PS:0表示緩沖區(qū)可掛起的連接數(shù)量?0表示不限制,1表示?可掛起一個,那么意思就是連接一個、掛起一個,第三個再連接的話,就無法連接,會超時?
4.接收客戶端建立連接的請求
conn,addr?=?s.accept() PS:conn為一個客戶端和服務(wù)器建立的連接,addr為客戶端ip?
5.接收客戶端的消息,并做相應(yīng)處理
recv_data?=?conn.recv(1024) send_data?=?recv_data.upper()??#將客戶端發(fā)送的內(nèi)容轉(zhuǎn)換為大寫,注意。python3里面客戶端發(fā)送的都是二進制數(shù)據(jù),python2里可以發(fā)送字符串?
6.給客戶端回消息
conn.send(send_data)?
7.關(guān)閉連接
conn.close()?
客戶端
import?sockets?=?socket.socket()
1.創(chuàng)建套接字?
2.連接服務(wù)端
ip_port?=?('127.0.0.1',8080) s.connect(ip_port)?
3.給服務(wù)端發(fā)送消息
send_data?=?input('請輸入:?') s.send(send_data.encode())??#注意py3發(fā)送的數(shù)據(jù)需要轉(zhuǎn)換為二進制,不能直接發(fā)送字符串?
4.接收服務(wù)端消息,并打印
recv_data?=?s.recv(1024)print(recv_data.decode())??#服務(wù)端回應(yīng)的是二進制,所以需要轉(zhuǎn)換為字符串?
5.關(guān)閉連接
s.close()?
以上就是一個簡單的客戶端和服務(wù)端socket連接,并發(fā)送消息,讀消息,回消息的過程,初學(xué)者可能一下子就懵了,請看下面的類比,
類比
通過上面的服務(wù)端和客戶端的一個簡單的交互,可以將其比作打電話,小明是服務(wù)端,小紅是客戶端小紅:你好 此時小紅是發(fā)消息,小明此時處于收消息的狀態(tài)
小明:你好 小明收到小紅發(fā)的你好消息,做出回應(yīng),此時小明開始給小紅發(fā)消息,小紅處于收消息狀態(tài)
最后小紅收到了小明的消息,小明此時已經(jīng)掛斷電話,最后此次通信已斷注意此次通信只是一個簡單的交互過程,交互完成之后,則先完成方會主動關(guān)系連接。如果要持續(xù)通信,請繼續(xù)往下看
小明
小紅
小紅和小明交互
小紅在和小明打電話前得有個通信工具等等,所以需要找到一部手機,類同創(chuàng)建一個套接字
小紅需要知道小明的電話號碼,并撥打電話,此步驟就等于客戶端連接服務(wù)端
小明為了接收電話,他首先得買個手機,此步驟類同創(chuàng)建socket套接字
小明有了手機,需要辦一張電話卡,此步驟類同綁定套接字搭配監(jiān)聽的ip和端口
小明有了手機和電話卡,則手機開機,處于待機狀態(tài) 此步驟類同監(jiān)聽客戶端連接
當(dāng)小紅打電話進來之后,需要接電話,此類同于接收客戶端建立連接的請求
服務(wù)端
import?socketip_port?=?('127.0.0.1',8080)s?=?socket.socket() s.bind(ip_port)s.listen(0)while?True:????#此次while循環(huán)用于客戶端斷開連接之后,重新循環(huán)建立新連接conn,addr?=?s.accept()????while?True:????#此while循環(huán)用于客戶端和服務(wù)器持續(xù)交互recv_data?=?conn.recv(1024)???????if?not?recv_data:?break???#判斷消息是否為空,當(dāng)消息為空時,跳出循環(huán),如果不判斷的話,客戶端那邊如果主動斷開連接,將會導(dǎo)致服務(wù)端處于一個不停的收消息的死循環(huán)中,因為連接已斷開,處于非阻塞狀態(tài)send_data?=?recv_data.upper()??#將客戶消息轉(zhuǎn)換為大寫conn.send(send_data)conn.close()
?
客戶端:
import?sockets?=?socket.socket()ip_port?=?('127.0.0.1',8080)s.connect(ip_port)while?True:send_data?=?input('請輸入:?')????if?send_data?==?'exit':breakelif?send_data?==?'':continues.send(send_data.encode())recv_data?=?s.recv(1024)????print(recv_data.decode()) s.close()
?
運行服務(wù)端和客戶端,效果如下:
請輸入:?hello HELLO 請輸入:?Jeck JECK 請輸入:?123 123請輸入:? 請輸入:?exitProcess?finished?with?exit?code?0
?
socket模塊功能
socket 類型
socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
參數(shù)一:地址簇
socket.AF_INET IPv4(默認)
socket.AF_INET6 IPv6
socket.AF_UNIX 只能夠用于單一的Unix系統(tǒng)進程間通信參數(shù)二:類型
socket.SOCK_STREAM 流式socket , for TCP (默認)
socket.SOCK_DGRAM 數(shù)據(jù)報式socket , for UDP
socket.SOCK_RAW 原始套接字,普通的套接字無法處理ICMP、IGMP等網(wǎng)絡(luò)報文,而SOCK_RAW可以;其次,SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由用戶構(gòu)造IP頭。
socket.SOCK_RDM 是一種可靠的UDP形式,即保證交付數(shù)據(jù)報但不保證順序。SOCK_RAM用來提供對原始協(xié)議的低級訪問,在需要執(zhí)行某些特殊操作時使用,如發(fā)送ICMP報文。SOCK_RAM通常僅限于高級用戶或管理員運行的程序使用。
socket.SOCK_SEQPACKET 可靠的連續(xù)數(shù)據(jù)包服務(wù)參數(shù)三:協(xié)議
0 (默認)與特定的地址家族相關(guān)的協(xié)議,如果是 0 ,則系統(tǒng)就會根據(jù)地址格式和套接類別,自動選擇一個合適的協(xié)議
socket方法
將套接字綁定到地址。address地址的格式取決于地址族。在AF_INET下,以元組(host,port)的形式表示地址。
是否阻塞(默認True),如果設(shè)置False,那么accept和recv時一旦無數(shù)據(jù),則報錯。
接受連接并返回(conn,address),其中conn是新的套接字對象,可以用來接收和發(fā)送數(shù)據(jù)。address是連接客戶端的地址。
接收TCP 客戶的連接(阻塞式)等待連接的到來連接到address處的套接字。一般,address的格式為元組(hostname,port),如果連接出錯,返回socket.error錯誤。
同上,只不過會有返回值,連接成功時返回 0 ,連接失敗時候返回編碼,例如:10061
關(guān)閉套接字
接受套接字的數(shù)據(jù)。數(shù)據(jù)以字符串形式返回,bufsize指定最多可以接收的數(shù)量。flag提供有關(guān)消息的其他信息,通常可以忽略
與recv()類似,但返回值是(data,address)。其中data是包含接收數(shù)據(jù)的字符串,address是發(fā)送數(shù)據(jù)的套接字地址。
將string中的數(shù)據(jù)發(fā)送到連接的套接字。返回值是要發(fā)送的字節(jié)數(shù)量,該數(shù)量可能小于string的字節(jié)大小。即:可能未將指定內(nèi)容全部發(fā)送。
將string中的數(shù)據(jù)發(fā)送到連接的套接字,但在返回之前會嘗試發(fā)送所有數(shù)據(jù)。成功返回None,失敗則拋出異常。內(nèi)部通過遞歸調(diào)用send,將所有內(nèi)容發(fā)送出去。
將數(shù)據(jù)發(fā)送到套接字,address是形式為(ipaddr,port)的元組,指定遠程地址。返回值是發(fā)送的字節(jié)數(shù)。該函數(shù)主要用于UDP協(xié)議。
設(shè)置套接字操作的超時期,timeout是一個浮點數(shù),單位是秒。值為None表示沒有超時期。一般,超時期應(yīng)該在剛創(chuàng)建套接字時設(shè)置,因為它們可能用于連接的操作(如 client 連接最多等待5s )
返回連接套接字的遠程地址。返回值通常是元組(ipaddr,port)。
返回套接字自己的地址。通常是一個元組(ipaddr,port)
sk.fileno()
sk.getsockname()
sk.getpeername()
sk.settimeout(timeout)
sk.sendto(string[,flag],address)
sk.sendall(string[,flag])
sk.send(string[,flag])
sk.recvfrom(bufsize[.flag])
sk.recv(bufsize[,flag])
sk.close()
sk.connect_ex(address)
sk.connect(address)
sk.accept()
sk.listen(backlog)
開始監(jiān)聽傳入連接。backlog指定在拒絕連接之前,可以掛起的最大連接數(shù)量。backlog等于5,表示內(nèi)核已經(jīng)接到了連接請求,但服務(wù)器還沒有調(diào)用accept進行處理的連接個數(shù)最大為5,這個值不能無限大,因為要在內(nèi)核中維護連接隊列sk.setblocking(bool)
sk.bind(address)
套接字的文件描述符
案例:模擬ssh
服務(wù)端:
import?socketimport??subprocessip_port?=?('127.0.0.1',8080)s?=?socket.socket() s.bind(ip_port)s.listen(0)while?True:conn,addr?=?s.accept()????while?True:????????try:recv_data?=?conn.recv(1024)????????????if?not?recv_data:?breakp?=?subprocess.Popen(str(recv_data,encoding='utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)????#執(zhí)行shell命令,并將標(biāo)準輸出和錯誤輸出放到緩沖區(qū)res?=?p.stdout.read()????????????if?not?res:send_data?=?p.stderr.read()????????????else:send_data?=?resdata_size?=?len(send_data)conn.send(send_data)????????except?Exception:????????????breakconn.close()
?
*?客戶端import?socketip_port?=?('127.0.0.1',8080)s?=?socket.socket()s.connect(ip_port)while?True:send_data?=?input('>>:??')????if?send_data?==?'exit':exit()????elif?not?send_data:continues.send(bytes(send_data,encoding='utf-8'))recv_data?=?s.recv(1024)????print(recv_data.decode()) s.close()
?
執(zhí)行結(jié)果:
>>:??df?-h Filesystem??????Size??Used?Avail?Use%?Mounted?on/dev/disk1??????112G???51G???62G??45%?/>>:??netstat?-lnt Active?Internet?connections Proto?Recv-Q?Send-Q??Local?Address??????????Foreign?Address????????(state)???? tcp4???????0??????0??172.16.23.42.57334?????23.83.227.252.8023?????ESTABLISHED tcp4???????0??????0??127.0.0.1.1080?????????127.0.0.1.57333????????ESTABLISHED tcp4???????0??????0??127.0.0.1.57333????????127.0.0.1.1080?????????ESTABLISHED tcp4???????0??????0??127.0.0.1.8080?????????127.0.0.1.57332????????ESTABLISHED tcp4???????0??????0??127.0.0.1.57332????????127.0.0.1.8080?????????ESTABLISHED tcp4???????0??????0??172.16.23.42.57328?????223.252.199.7.80???????CLOSE_WAIT? tcp4???????0??????0??172.16.23.42.57269?????163.177.72.143.993?????ESTABLISHED tcp4???????0??????0??10.255.0.10.57047??????203.130.45.175.9000????ESTABLISHED tcp4??????27??????0??172.16.23.42.57045?????163.177.90.125.993?????CLOSE_WAIT? tcp4???????0??????0??172.16.23.42.56988?????114.215.186.163.443????ESTABLISHED tcp4??????27??????0??172.16.23.42.56632?????163.177.72.143.993?????CLOSE_WAIT? tcp4???????0??????0??10.255.0.10.56374??????10.2 >>:??route?-n0.7.12.22??????????ESTABLISHED tcp4??????27??????0??172.16.23.42.56229?????163.177.90.125.993?????CLOSE_WAIT? tcp4???????0??????0??10.255.0.10.54889??????203.130.45.175.9000????ESTABLISHED tcp4???????0??????0??10.255.0.10.54605??????203.130.45.173.6929????ESTABLISHED tcp4???????0??????0??10.255.0.10.53228??????10.20.7.12.22??????????ESTABLISHED tcp4???????0??????0??10.255.0.10.53122??????203.130.45.175.9000????ESTABLISHED tcp4???????0??????0??172.16.23.42.52902?????42.62.89.250.1194??????ESTABLISHED tcp4???????0??????0??127.0.0.1.1337?????????127.0.0.1.52901????????ESTABLISHED tcp4???????0??????0??127.0.0.1.52901????????127.0.0.1.1337?????????ESTABLISHED tcp4???????0??????0??172.16.23.42.52899?????17.172.232.10.5223?????ESTABLISHED tcp4???????0??????0??172.16.23.42.52855?????17.252.236.157.5223????ESTABLISHED tcp4???????0??????0??172.16.23.42.52790?????223.252.199.6.6003?????ESTABLISHED tcp4???????0??????0??172.16.23.42.50124?????223.167.82.210.80??????ESTABLISHED tcp4???????0??????0??172.16.23.42.50026?????1
?
從結(jié)果中發(fā)現(xiàn),執(zhí)行df -h 返回正常結(jié)果,執(zhí)行netstat -lnt返回了一半的結(jié)果,繼續(xù)執(zhí)行命令,仍然返回的是netstat -lnt的結(jié)果,這就發(fā)生了粘包現(xiàn)象
粘包解決
所謂粘包現(xiàn)象就是服務(wù)端把數(shù)據(jù)發(fā)過來之后,客戶端接收時會按一定大小來接收,決定此操作的是s.recv(1024),1024是每次接收的包大小,第一次沒有接收完的話,第二次會繼續(xù)接收原來的數(shù)據(jù)包,這就是粘包現(xiàn)象,解決辦法就是,服務(wù)端在發(fā)送數(shù)據(jù)時,現(xiàn)告訴客戶端本次數(shù)據(jù)的大小,然后再發(fā)送數(shù)據(jù),客戶端收到數(shù)據(jù)大小之后,循環(huán)接收數(shù)據(jù),知道接收完成再終止此次循環(huán),這樣就可以拿到所有的數(shù)據(jù),解決了粘包現(xiàn)象
服務(wù)端改造:
#!/usr/bin/env?python#?-*-?coding:?UTF-8?-*-#pyversion:python3.5#owner:fuzjimport?socketimport??subprocessip_port?=?('127.0.0.1',8080)s?=?socket.socket() s.bind(ip_port)s.listen(0)while?True:conn,addr?=?s.accept()????while?True:????????try:recv_data?=?conn.recv(1024)????????????if?not?recv_data:?breakp?=?subprocess.Popen(str(recv_data,encoding='utf-8'),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)res?=?p.stdout.read()????????????if?not?res:send_data?=?p.stderr.read()????????????else:send_data?=?resdata_size?=?len(send_data)???#計算數(shù)據(jù)大小conn.send(bytes(str(data_size),encoding='utf-8'))??#發(fā)送數(shù)據(jù)大小res?=?conn.recv(1024)??#接收客戶端狀態(tài)conn.send(send_data)???#發(fā)送數(shù)據(jù)????????except?Exception:????????????breakconn.close()
?
*?客戶端改造:import?socketip_port?=?('127.0.0.1',8080)s?=?socket.socket()s.connect(ip_port)while?True:send_data?=?input('>>:??')????if?send_data?==?'exit':exit()????elif?not?send_data:continues.send(bytes(send_data,encoding='utf-8'))recv_size?=?0data?=?b''data_size?=?str(s.recv(1024),encoding='utf-8')??#接收數(shù)據(jù)大小s.send(bytes('ok',encoding='utf-8'))??#發(fā)送此時的狀態(tài)????while?recv_size?<?int(data_size):????#循環(huán)接收數(shù)據(jù),直到接收完所有數(shù)據(jù)recv_data?=?s.recv(1024)data?+=?recv_datarecv_size?+=?len(recv_data)????print(str(data,encoding='utf-8'))s.close()
?
運行結(jié)果:發(fā)現(xiàn)已經(jīng)解決上述問題
>>:??df?-h Filesystem??????Size??Used?Avail?Use%?Mounted?on/dev/disk1??????112G???51G???62G??45%?/>>:??netstat?-lnt Active?Internet?connections Proto?Recv-Q?Send-Q??Local?Address??????????Foreign?Address????????(state)???? tcp4???????0??????0??172.16.23.42.57476?????223.252.199.7.80???????CLOSE_WAIT? tcp4???????0??????0??127.0.0.1.8080?????????127.0.0.1.57475????????ESTABLISHED tcp4???????0??????0??127.0.0.1.57475????????127.0.0.1.8080?????????ESTABLISHED tcp4???????0??????0??172.16.23.42.57474?????223.252.199.7.80???????LAST_ACK??? tcp4???????0??????0??172.16.23.42.57465?????23.83.227.252.8023?????ESTABLISHED tcp4???????0??????0??127.0.0.1.1080?????????127.0.0.1.57464????????ESTABLISHED tcp4???????0??????0??127.0.0.1.57464????????127.0.0.1.1080?????????ESTABLISHED tcp4???????0??????0??172.16.23.42.57461?????23.83.227.252.8023?????ESTABLISHED tcp4???????0??????0??127.0.0.1.1080?????????127.0.0.1.57460????????ESTABLISHED tcp4???????0??????0??127.0.0.1.57460????????127.0.0.1.1080?????????ESTABLISHED tcp4???????0??????0??172.16.23.42.57455?????163.177.72.143.993?????CLOSE_WAIT? tcp4???????0??????0??10.255.0.10.57047??????203.130.45.175.9000????ESTABLISHED tcp4??????27??????0??172.16.23.42.57045?????163.177.90.125.993?????CLOSE_WAIT? tcp4???????0??????0??172.16.23.42.56988?????114.215.186.163.443????ESTABLISHED tcp4??????27??????0??172.16.23.42.56632?????163.177.72.143.993?????CLOSE_WAIT? tcp4???????0??????0??10.255.0.10.56374??????10.20.7.12.22??????????ESTABLISHED tcp4??????27??????0??172.16.23.42.56229?????163.177.90.125.993?????CLOSE_WAIT? tcp4???????0??????0??10.255.0.10.54889??????203.130.45.175.9000????ESTABLISHED tcp4???????0??????0??10.255.0.10.54605??????203.130.45.173.6929????ESTABLISHED tcp4???????0??????0??10.255.0.10.53228??????10.20.7.12.22??????????ESTABLISHED tcp4???????0??????0??10.255.0.10.53122??????203.130.45.175.9000????ESTABLISHED tcp4???????0??????0??172.16.23.42.52902?????42.62.89.250.1194??????ESTABLISHED tcp4???????0??????0??127.0.0.1.1337?????????127.0.0.1.52901????????ESTABLISHED tcp4???????0??????0??127.0.0.1.52901????????127.0.0.1.1337?????????ESTABLISHED tcp4???????0??????0??172.16.23.42.52899?????17.172.232.10.5223?????ESTABLISHED tcp4???????0??????0??172.16.23.42.52855?????17.252.236.157.5223????ESTABLISHED tcp4???????0??????0??172.16.23.42.52790?????223.252.199.6.6003?????ESTABLISHED tcp4???????0??????0??172.16.23.42.50124?????223.167.82.210.80??????ESTABLISHED tcp4???????0??????0??172.16.23.42.50026?????123.151.10.187.14000???ESTABLISHED tcp4???????0??????0??172.16.23.42.49612?????163.177.90.125.993?????ESTABLISHED tcp4???????0??????0??127.0.0.1.49871????????127.0.0.1.49375????????ESTABLISHED tcp4???????0??????0??127.0.0.1.49375????????127.0.0.1.49871????????ESTABLISHED tcp4???????0??????0??127.0.0.1.49871????????127.0.0.1.49370????????ESTABLISHED tcp4???????0??????0??127.0.0.1.49370????????127.0.0.1.49871????????ESTABLISHED tcp4???????0??????0??192.168.123.164.49282??112.90.83.61.443???????ESTABLISHED
?
socketserver 實現(xiàn)支持多客戶端
上述ssh模擬客戶端只能支持一定數(shù)量的客戶端,受s.listen(0)參數(shù)限制。下面可以實現(xiàn)支持多客戶端操作
SocketServer內(nèi)部使用 IO多路復(fù)用 以及 “多線程” 和 “多進程” ,從而實現(xiàn)并發(fā)處理多個客戶端請求的Socket服務(wù)端。即:每個客戶端請求連接到服務(wù)器時,Socket服務(wù)端都會在服務(wù)器是創(chuàng)建一個“線程”或者“進程” 專門負責(zé)處理當(dāng)前客戶端的所有請求
ThreadingTCPServer
ThreadingTCPServer實現(xiàn)的Soket服務(wù)器內(nèi)部會為每個client創(chuàng)建一個 “線程”,該線程用來和客戶端進行交互
實現(xiàn)步驟:
1.創(chuàng)建一個類,并繼承SocketServer.BaseRequestHandler 的類
2.在新類中需要創(chuàng)建一個handle的方法
3.啟動ThreadingTCPServer
代碼如下:
import?socketserverimport?subprocessclass?MyServer(socketserver.BaseRequestHandler):??#繼承????def?handle(self):???#handle方法。注意此時send和recv時調(diào)用的self.request方法self.request.sendall(bytes('Welcome',encoding='utf-8'))????????while?True:????????????try:recv_data?=?self.request.recv(1024)????????????????if?not?recv_data:?breakp?=?subprocess.Popen(str(recv_data,?encoding='utf-8'),?shell=True,?stdout=subprocess.PIPE,stderr=subprocess.PIPE)res?=?p.stdout.read()????????????????if?not?res:send_data?=?p.stderr.read()????????????????else:send_data?=?res????????????????if?not?send_data:send_data?=?'no?output'.encode()data_size?=?len(send_data)self.request.send(bytes(str(data_size),?encoding='utf-8'))self.request.recv(1024)self.request.send(send_data)????????????except?Exception:????????????????breakif?__name__?==?'__main__':server?=?socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyServer)????#啟動serverserver.serve_forever()
?
PS:SocketServer.BaseRequestHandler類源碼:其定義了三個方法:setup(),handle()he finish()
執(zhí)行順序為:setup(0-->handle()-->finish()
```
class?BaseRequestHandler:def?__init__(self,?request,?client_address,?server):self.request?=?requestself.client_address?=?client_addressself.server?=?serverself.setup()????try:self.handle()????finally:self.finish()def?setup(self):????passdef?handle(self):????passdef?finish(self):????passSocketServer.BaseRequestHandler
?
```
ThreadingTCPServer源碼剖析
內(nèi)部調(diào)用流程
啟動服務(wù)端程序
執(zhí)行 TCPServer.__init__ 方法,創(chuàng)建服務(wù)端Socket對象并綁定 IP 和 端口
執(zhí)行 BaseServer.__init__ 方法,將自定義的繼承自SocketServer.BaseRequestHandler 的類 MyRequestHandle賦值給 self.RequestHandlerClass
執(zhí)行 BaseServer.server_forever 方法,While 循環(huán)一直監(jiān)聽是否有客戶端請求到達 ...
當(dāng)客戶端連接到達服務(wù)器
執(zhí)行 ThreadingMixIn.process_request 方法,創(chuàng)建一個 “線程” 用來處理請求
執(zhí)行 ThreadingMixIn.process_request_thread 方法
執(zhí)行 BaseServer.finish_request 方法,執(zhí)行 self.RequestHandlerClass() 即:執(zhí)行 自定義 MyRequestHandler 的構(gòu)造方法(自動調(diào)用基類BaseRequestHandler的構(gòu)造方法,在該構(gòu)造方法中又會調(diào)用 MyRequestHandler的handle方法)
轉(zhuǎn)載于:https://blog.51cto.com/studys/1827235
總結(jié)
以上是生活随笔為你收集整理的socket编程初级的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下搭建FTP服务器
- 下一篇: android view getx 0,