Python實(shí)現(xiàn)一個(gè)服務(wù)器監(jiān)聽多個(gè)客戶端請(qǐng)求
學(xué)習(xí)Python網(wǎng)絡(luò)通信的時(shí)候發(fā)現(xiàn)書上只有一個(gè)服務(wù)端對(duì)應(yīng)一個(gè)客戶端的情形,于是自己想自己動(dòng)手實(shí)現(xiàn)一個(gè)服務(wù)端響應(yīng)多個(gè)客戶端。
首先建立服務(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á)成!
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Python 通過監(jiān)聽端口實(shí)現(xiàn)唯一腳本運(yùn)行方式
- Python2.7:使用Pyhook模塊監(jiān)聽鼠標(biāo)鍵盤事件-獲取坐標(biāo)實(shí)例
- python利用wx實(shí)現(xiàn)界面按鈕和按鈕監(jiān)聽和字體改變的方法
- Python寫一個(gè)基于MD5的文件監(jiān)聽程序
- python 監(jiān)聽salt job狀態(tài),并任務(wù)數(shù)據(jù)推送到redis中的方法
- python hook監(jiān)聽事件詳解
- Python文件監(jiān)聽工具pyinotify與watchdog實(shí)例
- Python簡(jiǎn)單實(shí)現(xiàn)socket信息發(fā)送與監(jiān)聽功能示例
- Python利用pyHook實(shí)現(xiàn)監(jiān)聽用戶鼠標(biāo)與鍵盤事件
- Python中使用PyHook監(jiān)聽鼠標(biāo)和鍵盤事件實(shí)例
- Python監(jiān)聽剪切板實(shí)現(xiàn)方法代碼實(shí)例
相關(guān)文章
Python基于Tkinter實(shí)現(xiàn)的記事本實(shí)例
這篇文章主要介紹了Python基于Tkinter實(shí)現(xiàn)的記事本,實(shí)例分析了Tkinter實(shí)現(xiàn)記事本程序的相關(guān)技巧,需要的朋友可以參考下2015-06-06Python使用conda如何安裝requirement.txt的擴(kuò)展包
這篇文章主要介紹了Python使用conda如何安裝requirement.txt的擴(kuò)展包問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02python使用pandas實(shí)現(xiàn)Excel轉(zhuǎn)換為CSV文件
在數(shù)據(jù)處理和分析中,我們經(jīng)常需要將 Excel 文件轉(zhuǎn)換為 CSV 格式,這篇文章我們主要來介紹一下python如何使用pandas實(shí)現(xiàn)Excel轉(zhuǎn)換為CSV文件,希望對(duì)大家有所幫助2024-10-10Python?clip與range函數(shù)保姆級(jí)使用教程
本文主要和大家介紹了詳解Python中clip與range函數(shù)的用法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參,希望能幫助到大家2022-06-06windows 下python+numpy安裝實(shí)用教程
這篇文章主要介紹了windows 下python+numpy安裝實(shí)用教程,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12Python壓縮模塊zipfile實(shí)現(xiàn)原理及用法解析
這篇文章主要介紹了Python壓縮模塊zipfile實(shí)現(xiàn)原理及用法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08VSCode中autopep8無法運(yùn)行問題解決方案(提示Error: Command failed,usage)
這篇文章主要介紹了VSCode中autopep8無法運(yùn)行問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03python實(shí)現(xiàn)音樂播放器 python實(shí)現(xiàn)花框音樂盒子
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)音樂播放器,實(shí)現(xiàn)花框音樂盒子,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02利用Pycharm + Django搭建一個(gè)簡(jiǎn)單Python Web項(xiàng)目的步驟
這篇文章主要介紹了利用Pycharm + Django搭建一個(gè)簡(jiǎn)單Python Web項(xiàng)目的步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10