2

TCL ソケット コマンドを使用して、2 つの TCL/Tk アプリケーション (A と B) の間で通信を行っています。どちらも GUI が関連付けられています。B 上のサーバーは、基本的に A からのコマンドを受け入れ、実行結果を返します。問題は、実行が完了するとすぐに B の GUI がハングすることです。2 つの GUI を独立して動作させる方法はありますか? 次のスクリプトを使用して、2 つのアプリケーション間の接続をセットアップしています。

次の TCL スクリプト client.tcl でアプリケーション A を開始します。

proc execute { cmd } {
    set cid [socket localhost 9900]
    puts $cid $cmd
    while { [gets $cid line] >= 0 } {
        puts $line
    } 
    close $cid
}

set pid [exec B server.tcl &]

execute {puts HelloWorld}

ここで、server.tcl はアプリケーション B を介してサーバーをセットアップします。

proc server { cid addr port } {
     set cmd [gets $cid]
     catch $cmd result
     puts $cid result
     close $cid
}

socket -server server 9900

vwait forever

目標は、ユーザーが A の GUI で作業を続けている間、B の GUI をアクティブにすることです。これにより、ユーザーは必要に応じて 2 つの GUI を切り替えることができます。A と B はどちらも、同時に利用可能にする必要がある同じデータを操作するための異なる機能を提供します。

4

1 に答える 1

2

投稿したコードには2つの重要な問題があります。

  1. パフォーマンス上の理由から、デフォルト以外のチャネル(stdin、stdout、stderrではない)はデフォルトで完全にバッファリングされるため、クライアントは、作業の一部(つまり、実行するコマンド)を書き込んだ後、ソケットをフラッシュしません。これにより、サーバーが最初からコマンドを実際に受信しなくなる可能性があります。

  2. fileeventサーバーは、 -registeredスクリプトを介して、受け入れられたソケットを非ブロッキングモードで処理しません。

また、複数行のデータを送信したい場合は、プロトコルが不十分であることに気付くというわずかな問題があります。あなたはこれを気にするかもしれないし気にしないかもしれません、そしてそれを修正するいくつかの異なる方法があります。

重要な問題1

クライアントの大きな問題に対処する最良の方法は、を使用することです

fconfigure $cid -buffering none

ソケットを開いた直後。これは、Tclに、常にデータをputsソケットのチャネルにすぐに送信する必要があることを示しています。(または、line代わりにnoneを使用して行のバッファリングを取得します。この場合も十分に機能します。)明示的なフラッシュを実行することもできます。

flush $cid

それはの後に行きputsます。

重要な問題2

ベストプラクティスは、このようなサーバースクリプトを使用し、1つの手順で受け入れられたソケット接続のサービスを設定し、別の手順でメッセージの読み取りと書き込みを処理します。acceptプロシージャ(server)はブロッキングをオフにし(多くの場合、バッファリングも調整します)、操作プロシージャ(readLine)はとを使用eofして成功したか失敗しfblockedたかを判断します。gets

proc server { cid addr port } {
    fconfigure $cid -blocking 0
    fileevent $cid readable "readLine $cid"
}

proc readLine { cid } {
    set cmd [gets $cid]
    if { [eof $cid] } {
        close $cid
    } elseif { ![fblocked $cid] } {
        catch $cmd result
        puts $cid $result
        close $cid
    }
}

socket -server server 9900
vwait forever

その他の問題

これを実際に行っている場合のもう1つの大きな問題は、複数行のメッセージが役立つことです。readLineコマンド全体が揃うまで上記の累積行を作成する必要があるか(ここappendinfo completeヘルプが表示されます)、データ転送を処理するための他のメカニズムが必要になります。本番コードでは、commのようなパッケージに委任するのが簡単になります…</ p>

于 2013-01-06T23:05:57.600 に答える