Python實現(xiàn)一個服務(wù)器監(jiān)聽多個客戶端請求
學(xué)習(xí)Python網(wǎng)絡(luò)通信的時候發(fā)現(xiàn)書上只有一個服務(wù)端對應(yīng)一個客戶端的情形,于是自己想自己動手實現(xiàn)一個服務(wù)端響應(yīng)多個客戶端。
首先建立服務(wù)器的socket來監(jiān)聽客戶端的請求:
tcpSerSock=socket(AF_INET,SOCK_STREAM) tcpSerSock.bind(ADDR) tcpSerSock.listen(5)
這樣服務(wù)器的監(jiān)聽socket就建好了。
接下來的思路是,如果要監(jiān)聽多個客戶端,則
tcpSerSock.accept() #(accept()是阻塞式的)
必須放進一個while循環(huán)(不放進循環(huán)監(jiān)聽一次就沒了)。然而,這里就有問題了。如果按照一對一的那種處理順序,客戶端A連進來后,程序順序向下執(zhí)行,服務(wù)端要再寫一個while循環(huán),用來處理客戶端A的請求,如果此時客戶端B再來請求,服務(wù)器將接收不到。于是,很自然想到,將監(jiān)聽和處理放到不同的線程進行處理。我選擇將監(jiān)聽放入主線程,將處理放進子線程。該服務(wù)器功能為接收到客戶端的數(shù)據(jù)加上時間戳后返回給客戶端。服務(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=[] #放每個客戶端的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)) #加上時間戳返回
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)
兩個客戶端A和B同時連接,服務(wù)器輸出:

可以看到服務(wù)端是可以相應(yīng)多個客戶端的。
客戶端A發(fā)條消息試試?

服務(wù)器返回來了帶時間戳的消息,goodjob。
那另一個呢?

很棒。服務(wù)器都能做出響應(yīng)。
再發(fā)一條試試?

發(fā)現(xiàn)服務(wù)器沒響應(yīng)了,這是怎么回事呢?
經(jīng)過仔細勘察發(fā)現(xiàn)是因為這句:
data = s.recv(BUFSIZ)
因為recv方法是阻塞的,也就是說,當(dāng)輪訓(xùn)到某個客戶端,比如A,這句等待A發(fā)消息,不發(fā)消息就不往下走,所以此時B再去發(fā)消息的話服務(wù)器就收不到了。
那該怎么辦呢?
很容易想到,將其設(shè)為非阻塞就好了。但上網(wǎng)找了好久,雖然找到可以用setblocking(0) 將套接字設(shè)為非阻塞,然而具體怎么用卻很少有人講清楚。查資料后終于搞明白,非阻塞的recv方法會繼續(xù)向下執(zhí)行,若超時得不到數(shù)據(jù)則會拋出異常。
修改后的代碼如下:
#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=[] #放每個客戶端的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)
此時再去嘗試:

客戶端隨便輸都會得到響應(yīng)。任務(wù)達成!
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Python 通過監(jiān)聽端口實現(xiàn)唯一腳本運行方式
- Python2.7:使用Pyhook模塊監(jiān)聽鼠標(biāo)鍵盤事件-獲取坐標(biāo)實例
- python利用wx實現(xiàn)界面按鈕和按鈕監(jiān)聽和字體改變的方法
- Python寫一個基于MD5的文件監(jiān)聽程序
- python 監(jiān)聽salt job狀態(tài),并任務(wù)數(shù)據(jù)推送到redis中的方法
- python hook監(jiān)聽事件詳解
- Python文件監(jiān)聽工具pyinotify與watchdog實例
- Python簡單實現(xiàn)socket信息發(fā)送與監(jiān)聽功能示例
- Python利用pyHook實現(xiàn)監(jiān)聽用戶鼠標(biāo)與鍵盤事件
- Python中使用PyHook監(jiān)聽鼠標(biāo)和鍵盤事件實例
- Python監(jiān)聽剪切板實現(xiàn)方法代碼實例
相關(guān)文章
Python flashtext文本搜索和替換操作庫功能使用探索
本文將深入介紹Python flashtext庫,包括其基本用法、功能特性、示例代碼以及實際應(yīng)用場景,以幫助大家更好地利用這個有用的工具2024-01-01
Python實現(xiàn)判斷并移除列表指定位置元素的方法
這篇文章主要介紹了Python實現(xiàn)判斷并移除列表指定位置元素的方法,涉及Python針對列表的索引范圍判斷及元素刪除等相關(guān)操作技巧,需要的朋友可以參考下2018-04-04
python opencv把一張圖片嵌入(疊加)到另一張圖片上的實現(xiàn)代碼
這篇文章主要介紹了python opencv把一張圖片嵌入(疊加)到另一張圖片上,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
15個應(yīng)該掌握的Jupyter Notebook使用技巧(小結(jié))
這篇文章主要介紹了15個應(yīng)該掌握的Jupyter Notebook使用技巧(小結(jié)),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Python學(xué)習(xí)之內(nèi)置函數(shù)總結(jié)
這篇文章主要為大家總結(jié)一下python?中常用的是個內(nèi)置函數(shù)的使用方法,文中的示例代碼講解詳細,對我們學(xué)習(xí)Python有一定的幫助,需要的可以參考一下2022-03-03

