欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python select.select模塊通信全過(guò)程解析

 更新時(shí)間:2017年09月20日 08:45:11   作者:又見(jiàn)阿郎  
這篇文章主要為大家解析了python select.select模塊通信全過(guò)程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

要理解select.select模塊其實(shí)主要就是要理解它的參數(shù), 以及其三個(gè)返回值。

select()方法接收并監(jiān)控3個(gè)通信列表, 第一個(gè)是所有的輸入的data,就是指外部發(fā)過(guò)來(lái)的數(shù)據(jù),第2個(gè)是監(jiān)控和接收所有要發(fā)出去的data(outgoing data),第3個(gè)監(jiān)控錯(cuò)誤信息

在網(wǎng)上一直在找這個(gè)select.select的參數(shù)解釋, 但實(shí)在是沒(méi)有, 哎...自己硬著頭皮分析了一下。
readable, writable, exceptional = select.select(inputs, outputs, inputs)

第一個(gè)參數(shù)就是服務(wù)器端的socket, 第二個(gè)是我們?cè)谶\(yùn)行過(guò)程中存儲(chǔ)的客戶端的socket, 第三個(gè)存儲(chǔ)錯(cuò)誤信息。
重點(diǎn)是在返回值, 第一個(gè)返回的是可讀的list, 第二個(gè)存儲(chǔ)的是可寫(xiě)的list, 第三個(gè)存儲(chǔ)的是錯(cuò)誤信息的
list。

這個(gè)也不必深究, 看看代碼自己分析下就能有大概理解。

網(wǎng)上所有關(guān)于select.select的代碼都是差不多的, 但是有些不能運(yùn)行, 或是不全。我自己重新寫(xiě)了一份能運(yùn)行的程序, 做了很多注釋, 好好看看就能搞懂

服務(wù)器端:

# coding: utf-8
import select
import socket
import Queue
from time import sleep


# Create a TCP/IP
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(False)

# Bind the socket to the port
server_address = ('localhost', 8090)
print ('starting up on %s port %s' % server_address)
server.bind(server_address)

# Listen for incoming connections
server.listen(5)

# Sockets from which we expect to read
inputs = [server]

# Sockets to which we expect to write
# 處理要發(fā)送的消息
outputs = []

# Outgoing message queues (socket: Queue)
message_queues = {}

while inputs:
 # Wait for at least one of the sockets to be ready for processing
 print ('waiting for the next event')
 # 開(kāi)始select 監(jiān)聽(tīng), 對(duì)input_list 中的服務(wù)器端server 進(jìn)行監(jiān)聽(tīng)
 # 一旦調(diào)用socket的send, recv函數(shù),將會(huì)再次調(diào)用此模塊
 readable, writable, exceptional = select.select(inputs, outputs, inputs)

 # Handle inputs
 # 循環(huán)判斷是否有客戶端連接進(jìn)來(lái), 當(dāng)有客戶端連接進(jìn)來(lái)時(shí)select 將觸發(fā)
 for s in readable:
  # 判斷當(dāng)前觸發(fā)的是不是服務(wù)端對(duì)象, 當(dāng)觸發(fā)的對(duì)象是服務(wù)端對(duì)象時(shí),說(shuō)明有新客戶端連接進(jìn)來(lái)了
  # 表示有新用戶來(lái)連接
  if s is server:
   # A "readable" socket is ready to accept a connection
   connection, client_address = s.accept()
   print ('connection from', client_address)
   # this is connection not server
   connection.setblocking(0)
   # 將客戶端對(duì)象也加入到監(jiān)聽(tīng)的列表中, 當(dāng)客戶端發(fā)送消息時(shí) select 將觸發(fā)
   inputs.append(connection)

   # Give the connection a queue for data we want to send
   # 為連接的客戶端單獨(dú)創(chuàng)建一個(gè)消息隊(duì)列,用來(lái)保存客戶端發(fā)送的消息
   message_queues[connection] = Queue.Queue()
  else:
   # 有老用戶發(fā)消息, 處理接受
   # 由于客戶端連接進(jìn)來(lái)時(shí)服務(wù)端接收客戶端連接請(qǐng)求,將客戶端加入到了監(jiān)聽(tīng)列表中(input_list), 客戶端發(fā)送消息將觸發(fā)
   # 所以判斷是否是客戶端對(duì)象觸發(fā)
   data = s.recv(1024)
   # 客戶端未斷開(kāi)
   if data != '':
    # A readable client socket has data
    print ('received "%s" from %s' % (data, s.getpeername()))
    # 將收到的消息放入到相對(duì)應(yīng)的socket客戶端的消息隊(duì)列中
    message_queues[s].put(data)
    # Add output channel for response
    # 將需要進(jìn)行回復(fù)操作socket放到output 列表中, 讓select監(jiān)聽(tīng)
    if s not in outputs:
     outputs.append(s)
   else:
    # 客戶端斷開(kāi)了連接, 將客戶端的監(jiān)聽(tīng)從input列表中移除
    # Interpret empty result as closed connection
    print ('closing', client_address)
    # Stop listening for input on the connection
    if s in outputs:
     outputs.remove(s)
    inputs.remove(s)
    s.close()

    # Remove message queue
    # 移除對(duì)應(yīng)socket客戶端對(duì)象的消息隊(duì)列
    del message_queues[s]

 # Handle outputs
 # 如果現(xiàn)在沒(méi)有客戶端請(qǐng)求, 也沒(méi)有客戶端發(fā)送消息時(shí), 開(kāi)始對(duì)發(fā)送消息列表進(jìn)行處理, 是否需要發(fā)送消息
 # 存儲(chǔ)哪個(gè)客戶端發(fā)送過(guò)消息
 for s in writable:
  try:
   # 如果消息隊(duì)列中有消息,從消息隊(duì)列中獲取要發(fā)送的消息
   message_queue = message_queues.get(s)
   send_data = ''
   if message_queue is not None:
    send_data = message_queue.get_nowait()
   else:
    # 客戶端連接斷開(kāi)了
    print "has closed "
  except Queue.Empty:
   # 客戶端連接斷開(kāi)了
   print "%s" % (s.getpeername())
   outputs.remove(s)
  else:
   # print "sending %s to %s " % (send_data, s.getpeername)
   # print "send something"
   if message_queue is not None:
    s.send(send_data)
   else:
    print "has closed "
   # del message_queues[s]
   # writable.remove(s)
   # print "Client %s disconnected" % (client_address)

 # # Handle "exceptional conditions"
 # 處理異常的情況
 for s in exceptional:
  print ('exception condition on', s.getpeername())
  # Stop listening for input on the connection
  inputs.remove(s)
  if s in outputs:
   outputs.remove(s)
  s.close()

  # Remove message queue
  del message_queues[s]

 sleep(1)

客戶端:

# coding: utf-8
import socket


messages = ['This is the message ', 'It will be sent ', 'in parts ', ]

server_address = ('localhost', 8090)

# Create aTCP/IP socket

socks = [socket.socket(socket.AF_INET, socket.SOCK_STREAM), socket.socket(socket.AF_INET, socket.SOCK_STREAM), ]

# Connect thesocket to the port where the server is listening

print ('connecting to %s port %s' % server_address)
# 連接到服務(wù)器
for s in socks:
 s.connect(server_address)

for index, message in enumerate(messages):
 # Send messages on both sockets
 for s in socks:
  print ('%s: sending "%s"' % (s.getsockname(), message + str(index)))
  s.send(bytes(message + str(index)).decode('utf-8'))
 # Read responses on both sockets

for s in socks:
 data = s.recv(1024)
 print ('%s: received "%s"' % (s.getsockname(), data))
 if data != "":
  print ('closingsocket', s.getsockname())
  s.close()

寫(xiě)代碼過(guò)程中遇到了兩個(gè)問(wèn)題, 一是如何判斷客戶端已經(jīng)關(guān)閉了socket連接, 后來(lái)自己分析了下, 如果關(guān)閉了客戶端socket, 那么此時(shí)服務(wù)器端接收到的data就是'', 加個(gè)這個(gè)判斷。二是如果服務(wù)器端關(guān)閉了socket, 一旦在調(diào)用socket的相關(guān)方法都會(huì)報(bào)錯(cuò), 不管socket是不是用不同的容器存儲(chǔ)的(意思是說(shuō)list_1存儲(chǔ)了socket1, list_2存儲(chǔ)了socket1, 我關(guān)閉了socket1, 兩者都不能在調(diào)用這個(gè)socket了)

客戶端:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Scrapy-Redis結(jié)合POST請(qǐng)求獲取數(shù)據(jù)的方法示例

    Scrapy-Redis結(jié)合POST請(qǐng)求獲取數(shù)據(jù)的方法示例

    這篇文章主要給大家介紹了關(guān)于Scrapy-Redis結(jié)合POST請(qǐng)求獲取數(shù)據(jù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Scrapy-Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Python?matplotlib如何簡(jiǎn)單繪制不同類型的表格

    Python?matplotlib如何簡(jiǎn)單繪制不同類型的表格

    通過(guò)Matplotlib,開(kāi)發(fā)者可以僅需要幾行代碼,便可以生成繪圖,直方圖,功率譜,條形圖,錯(cuò)誤圖,散點(diǎn)圖等,下面這篇文章主要給大家介紹了關(guān)于Python?matplotlib如何簡(jiǎn)單繪制不同類型表格的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • 詳解基于python-django框架的支付寶支付案例

    詳解基于python-django框架的支付寶支付案例

    這篇文章主要介紹了基于python-django框架的支付寶支付案例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 基于python連接oracle導(dǎo)并出數(shù)據(jù)文件

    基于python連接oracle導(dǎo)并出數(shù)據(jù)文件

    這篇文章主要介紹了基于python連接oracle導(dǎo)并出數(shù)據(jù)文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • python實(shí)現(xiàn)簡(jiǎn)單socket通信的方法

    python實(shí)現(xiàn)簡(jiǎn)單socket通信的方法

    這篇文章主要介紹了python實(shí)現(xiàn)簡(jiǎn)單socket通信的方法,結(jié)合實(shí)例形式分析了socket通信服務(wù)端與客戶端的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-04-04
  • python使用pandas庫(kù)導(dǎo)入并保存excel、csv格式文件數(shù)據(jù)

    python使用pandas庫(kù)導(dǎo)入并保存excel、csv格式文件數(shù)據(jù)

    CSV格式文件很方便各種工具之間傳遞數(shù)據(jù),平時(shí)工作過(guò)程之中會(huì)將數(shù)據(jù)保存為CSV格式,這篇文章主要介紹了python使用pandas庫(kù)導(dǎo)入并保存excel、csv格式文件數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2017-12-12
  • flask結(jié)合jinja2使用詳解

    flask結(jié)合jinja2使用詳解

    本文主要介紹了flask結(jié)合jinja2使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 原生python實(shí)現(xiàn)knn分類算法

    原生python實(shí)現(xiàn)knn分類算法

    這篇文章主要介紹了原生python實(shí)現(xiàn)knn分類算法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 解決python 讀取 log日志的編碼問(wèn)題

    解決python 讀取 log日志的編碼問(wèn)題

    今天小編就為大家分享一篇解決python 讀取 log日志的編碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • Python調(diào)用兩個(gè)機(jī)器人聊天的實(shí)戰(zhàn)

    Python調(diào)用兩個(gè)機(jī)器人聊天的實(shí)戰(zhàn)

    本文主要介紹了Python調(diào)用兩個(gè)機(jī)器人聊天,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09

最新評(píng)論