2016-08-26 1 views
0

私はむしろここでnoobですが、ソケットをポーリングできるスクリプトをセットアップしようとしています。ソケットデータが送信されていないときは、ループが実行され続け、他の処理が実行されます。私はselect()を使って見つかったいくつかの例を試してきましたが、コードをどのように整理しても、server.recv()行の上または近くで停止して応答を待つようです。クライアントからデータが送信されなかった場合、またはクライアント接続が存在しない場合は、これをスキップします。Pythonソケットセレクトがハングアップしています - ソケットデータを待っている間に他のタスクを実行していますか?

このアプリケーションでは、何らかの違いがあれば、返信データを送信するためのサーバースクリプトは必要ありません。

実際のアプリケーションは、ループを実行し、いくつかのLEDをアニメーション化することです(これは、Raspberry PiのI/Oへのルートアクセスが必要です)。私はアニメーションの制御パラメータを渡すソケットを介して別の別のスクリプトからこのスクリプトデータを送信します。このようにして、外部スクリプトはルートアクセスを必要としません。

これまでデータの送受信がうまくいっていますが、受信データがないと回転を続けることができません。これはselect()が許そうとしていたものだと私は理解していますが、私が見つけた例はそうした方法では動作していないようです。

server.setblocking(0)をいくつか別の場所に追加しようとしました。 (私が正しく理解していれば、データが送信されていなければ、recv()をスキップするコードを非ブロックのインスタンスで許可する必要がありますが、これはオフになっている可能性があります)。私はここに例の私のコードをベースとしている

http://ilab.cs.byu.edu/python/select/echoserver.html

ここでは、クライアント側のスクリプトに続いて、サーバー側のスクリプトです。

サーバコード:sockselectserver.py

#!/usr/bin/env python 

import select 
import socket 
import sys 

server = socket.socket() 
host = socket.gethostname() 
port = 20568 
size = 1024 
server.bind((host,port)) 
server.listen(5) 
input = [server,sys.stdin] 
running = 1 
while running: 
    inputready,outputready,exceptready = select.select(input,[],[]) 

    for s in inputready: 

     if s == server: 
      # handle the server socket 
      client, address = server.accept() 
      input.append(client) 

     elif s == sys.stdin: 
      # handle standard input 
      junk = sys.stdin.readline() 
      running = 0 

     else: 
      # handle all other sockets 
      data = s.recv(size) 
      if data: 
       s.send(data) 
      else: 
       s.close() 
       input.remove(s) 
    print "looping" 
server.close() 

クライアントコード:skclient.py

#!/usr/bin/python   # This is client.py file 

import socket    # Import socket module 

s = socket.socket()   # Create a socket object 
host = socket.gethostname() # Get local machine name 
port = 20568    # Reserve a port for your service. 

s.connect((host, port)) 

data = "123:120:230:51:210:120:55:12:35:24" 
s.send(data) 
print s.recv(1024) 
s.close      # Close the socket when done 

私はこの例で達成したいことを繰り返す "ループ" を参照してくださいすることですクライアントスクリプトがデータを送信したら、そのデータの印刷を参照してから、「ループ」の繰り返し印刷を繰り返してください。それは私がそこから取ることができる意図されていることをやっていると私に伝えます。

私はクライアントを実行するたびに、これをテストすると面白いですが、 "ループ"が画面に3回印刷されているのを確認しました。私は選択内で何が起こっているか完全に理解していませんが、1回だけ印刷すると仮定します。

select.select()を別の場所に移動しようとしましたが、毎回呼び出す必要があるようでした。それ以外の場合、サーバーは応答を停止します(たとえば、無限のwhile :ループ)。

これは、メーカークラスの他のハッカータイプに教えることができるほど簡単にできると思っています。だから、私はマルチスレッドとより精巧なソリューションであまりにも夢中になる必要はないと思っています。最後の手段として、私のすべてのパラメータを外部スクリプトからmySQLに記録し、このスクリプトを使用してテーブルから戻ってクエリを実行することを検討しています。私はそこに経験があり、おそらく動作するだろうが、このソケット角度はより直接的な解決策になると思われる。

ご協力いただきありがとうございます。

+0

サーバーは独自のループでなければなりません。imo – YOU

+0

クイック返信ありがとうございます。私はこれをどのように実装するのか分かりません。サンプルコードを共有することはできますか?私はループ内のすべてをラップしますか?もしそうなら、私は他の関数(クライアントが着信データを送信するときにのみ中断される何度も呼び出される関数)をどこで呼び出すでしょうか? – kjav

+0

'select.select(input、[]、[]、1)'オプションで 'select.select()'をタイムアウト(秒)オプションで呼び出してみてください。 – acw1668

答えて

0

素晴らしいニュースです。これは簡単な修正で、誰かがそれを必要とする場合に備えて投稿したかったのです。上記のacw1668からの提案は、私をつかまえました。

inputready,outputready,exceptready = select.select(input,[],[],0) 

これは、Pythonのドキュメントであるが、何とか私はそれを逃した:

は、単にこのようなselect.select()に「0」のタイムアウトを追加しました。ここにリンクする: https://docs.python.org/2/library/select.html

ドキュメント: "オプションのtimeout引数は、タイムアウトを秒単位で指定します。タイムアウト引数を省略すると、少なくとも1つのファイル記述子が準備完了になるまでブロックされます。タイムアウト値0は投票を指定し、決してブロックしません。

上記のコードと同じコードをテストし、印刷 "ループ"行の直後にtime.sleep(5)を使用して5秒の遅延を追加しました。遅れて、データまたはクライアントが存在しない場合、コードは単に5秒ごとにループし、スクリーンに「ループ」を印刷します。 5秒の遅延の間にクライアントスクリプトを開始すると、それは一時停止し、次の5秒の遅延が終了するとメッセージが処理されます。時折、次の非常にループに応答するのではなく、ループに応答します。これは、初めてserver.acceptが実行され、次回にs.recv()が実行されて実際にデータを交換するためと考えられます。

関連する問題