小編給大家分享一下Python如何實(shí)現(xiàn)一個(gè)服務(wù)器監(jiān)聽多個(gè)客戶端請(qǐng)求,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
成都創(chuàng)新互聯(lián)公司是一家集成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站頁面設(shè)計(jì)、網(wǎng)站優(yōu)化SEO優(yōu)化為一體的專業(yè)的建站公司,已為成都等多地近百家企業(yè)提供網(wǎng)站建設(shè)服務(wù)。追求良好的瀏覽體驗(yàn),以探求精品塑造與理念升華,設(shè)計(jì)最適合用戶的網(wǎng)站頁面。 合作只是第一步,服務(wù)才是根本,我們始終堅(jiān)持講誠(chéng)信,負(fù)責(zé)任的原則,為您進(jìn)行細(xì)心、貼心、認(rèn)真的服務(wù),與眾多客戶在蓬勃發(fā)展的市場(chǎng)環(huán)境中,互促共生。首先建立服務(wù)器的socket來監(jiān)聽客戶端的請(qǐng)求:
tcpSerSock=socket(AF_INET,SOCK_STREAM) tcpSerSock.bind(ADDR) tcpSerSock.listen(5)
這樣服務(wù)器的監(jiān)聽socket就建好了。
接下來的思路是,如果要監(jiān)聽多個(gè)客戶端,則
tcpSerSock.accept() #(accept()是阻塞式的)
必須放進(jìn)一個(gè)while循環(huán)(不放進(jìn)循環(huán)監(jiān)聽一次就沒了)。然而,這里就有問題了。如果按照一對(duì)一的那種處理順序,客戶端A連進(jìn)來后,程序順序向下執(zhí)行,服務(wù)端要再寫一個(gè)while循環(huán),用來處理客戶端A的請(qǐng)求,如果此時(shí)客戶端B再來請(qǐng)求,服務(wù)器將接收不到。于是,很自然想到,將監(jiān)聽和處理放到不同的線程進(jìn)行處理。我選擇將監(jiān)聽放入主線程,將處理放進(jìn)子線程。該服務(wù)器功能為接收到客戶端的數(shù)據(jù)加上時(shí)間戳后返回給客戶端。服務(wù)端完整代碼如下:
#coding=utf-8 #!/usr/bin/env python ''''' author:Mr.Jing created on Fri Sep 22 14:29:03 2017 platfrom:win10,python2.7 ''' from socket import * from time import ctime import threading import time HOST='' PORT=2159 BUFSIZ=1024 ADDR = (HOST,PORT) tcpSerSock=socket(AF_INET,SOCK_STREAM) tcpSerSock.bind(ADDR) tcpSerSock.listen(5) socks=[] #放每個(gè)客戶端的socket def handle(): while True: for s in socks: data = s.recv(BUFSIZ) if not data: socks.remove(s) continue s.send('[%s],%s' % (ctime(), data)) #加上時(shí)間戳返回 t = threading.Thread(target=handle) #子線程 if __name__ == '__main__': t.start() print u'我在%s線程中 ' % threading.current_thread().name #本身是主線程 print 'waiting for connecting...' while True: clientSock,addr = tcpSerSock.accept() print 'connected from:', addr socks.append(clientSock)
兩個(gè)客戶端A和B同時(shí)連接,服務(wù)器輸出:
可以看到服務(wù)端是可以相應(yīng)多個(gè)客戶端的。
客戶端A發(fā)條消息試試?
服務(wù)器返回來了帶時(shí)間戳的消息,goodjob。
那另一個(gè)呢?
很棒。服務(wù)器都能做出響應(yīng)。
再發(fā)一條試試?
發(fā)現(xiàn)服務(wù)器沒響應(yīng)了,這是怎么回事呢?
經(jīng)過仔細(xì)勘察發(fā)現(xiàn)是因?yàn)檫@句:
data = s.recv(BUFSIZ)
因?yàn)閞ecv方法是阻塞的,也就是說,當(dāng)輪訓(xùn)到某個(gè)客戶端,比如A,這句等待A發(fā)消息,不發(fā)消息就不往下走,所以此時(shí)B再去發(fā)消息的話服務(wù)器就收不到了。
那該怎么辦呢?
很容易想到,將其設(shè)為非阻塞就好了。但上網(wǎng)找了好久,雖然找到可以用setblocking(0) 將套接字設(shè)為非阻塞,然而具體怎么用卻很少有人講清楚。查資料后終于搞明白,非阻塞的recv方法會(huì)繼續(xù)向下執(zhí)行,若超時(shí)得不到數(shù)據(jù)則會(huì)拋出異常。
修改后的代碼如下:
#coding=utf-8 #!/usr/bin/env python ''''' author:Mr.Jing created on Fri Sep 22 14:29:03 2017 platfrom:win10,python2.7 ''' from socket import * from time import ctime import threading import time HOST='' PORT=2159 BUFSIZ=1024 ADDR = (HOST,PORT) tcpSerSock=socket(AF_INET,SOCK_STREAM) tcpSerSock.bind(ADDR) tcpSerSock.listen(5) socks=[] #放每個(gè)客戶端的socket def handle(): while True: for s in socks: try: data = s.recv(BUFSIZ) #到這里程序繼續(xù)向下執(zhí)行 except Exception, e: continue if not data: socks.remove(s) continue s.send('[%s],%s' % (ctime(), data)) t = threading.Thread(target=handle) #子線程 if __name__ == '__main__': t.start() print u'我在%s線程中 ' % threading.current_thread().name #本身是主線程 print 'waiting for connecting...' while True: clientSock,addr = tcpSerSock.accept() print 'connected from:', addr clientSock.setblocking(0) socks.append(clientSock)
此時(shí)再去嘗試:
客戶端隨便輸都會(huì)得到響應(yīng)。任務(wù)達(dá)成!
看完了這篇文章,相信你對(duì)“Python如何實(shí)現(xiàn)一個(gè)服務(wù)器監(jiān)聽多個(gè)客戶端請(qǐng)求”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,感謝各位的閱讀!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。