0

zeroconf/avahi、双方向 UDP 接続、および Qt インターフェイスを備えたネットワーク アプリケーションを Python で開発しています。私の双方向通信のために、UDP経由でリモートサーバーに接続し、サーバーが応答したい場合に備えてそのソケットでリッスンし続ける小さなクラスを作成しました。

私が本当に欲しいのは、私のネットワークコンポーネントに非同期レシーバーがあり、ピアからメッセージが到着したときにメッセージを実行して送信することです。もともと私SocketServerはこのタスクに使用していましたが、GUI のメインループの実行を開始するSocketServerと、呼び出しが停止することがすぐにわかりました。RequestHandler

だから私は少し調べて、これを見つけまし。これは私のニーズに適応しました。

残念ながら、私のアプリケーションはサーバーからデータが到着するとすぐにセグメンテーション違反を起こすようになりました。

問題を明らかにする小さなプログラムの例を次に示します。

import sys
import gobject
import socket
from PySide.QtCore import *
from PySide.QtGui import *

def callback(socket, *args):
    data, address = socket.recvfrom(8192)
    print "data arrived", data
    return True

class Client:
    def __init__(self, host, port):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.remote = (host, port)
        gobject.io_add_watch(self.socket, gobject.IO_IN, callback)
    def send(self, data=[]):
        self.socket.sendto( data,  self.remote)

class Form(QDialog):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        # widget
        self.button = QPushButton("Hello World")
        self.button.clicked.connect(self.sayHello)
        layout = QVBoxLayout()
        layout.addWidget(self.button)
        self.setLayout(layout) 
        self.connection = Client('localhost', 7777)
    def sayHello(self):
        self.connection.send('hello')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = Form()
    form.show()
    sys.exit(app.exec_())

私はこのように使用しています:

  • 始めるnetcat -u -l -p 7777
  • アプリケーションを開始する
  • ボタンをクリックします (netcat は「hello」と書き込みます)
  • netcat コンソールに何か入力して Enter キーを押します
  • →アプリが落ちる

今、問題は、glib と qt を混在させていることだと思います。どちらも (メインループに関して) 同様の機能を提供gobject.io_add_watchし、実行中の glib-mainloop に依存していますが、代わりに Qt メインループがあります。

PySide/Qt フレームワーク内で非同期受信 UDP クライアントを取得する適切な方法は何ですか? 可能であれば、組み込みのヘッドレス システム (ビーグルボーン) でネットワーク コードを再利用したいので、ネットワーク コードが Qt/PySide に依存するのを避けたいのですが、Qt はここでは少しやり過ぎのようです。

4

1 に答える 1

0

問題はかなり単純なようです。非スレッドをgobjectで使用する場合、それらを明示的に初期化する必要があります。

「 main」関数の先頭に次を追加すると、問題が解決します。

 gobject.threads_init()
于 2013-03-28T12:34:45.470 に答える