NCへのデータ配送の問題

NCへのデータ配送の問題

私はソケットを受け取り、コマンドを受け入れ、タスクを実行する小さなUDPサーバーをPHPで作成しました。これは実際には非常に基本的なものです。次のように手動で接続できます。

% nc -u host port

(ここでnc = Ncat:バージョン7.50(https://nmap.org/ncat))

コマンドを入力すると、結果の応答が表示されます。効果がある正確にコマンドラインで動作したい方法です。

しかし、次のようなファイルを「cat」すると、次のようになります。

cat FILE| nc -u host port

または、次のようにデータを送信します。

echo "command1\ncommand2\n" | nc -u host port

...そして私のPHPアプリケーションは、行末文字を含むすべてを一度に読みます。ただ最後まで読んでみたいですね。

もちろん、ファイルの内容をラップして各行を nc に送ることもできます。

for x in `cat <file>`; do
  echo $x | nc -u host port
done

...しかし、それは完全に無駄です。私はncへの1つの接続がほしいと思います。多くはありません。

PHPアプリケーションで出力を印刷すると、次のように表示されるため、EOL文字を文字列に入れます。 command1 command2...しかし、すべてが1つの文字列にあります。

対話型モードが非対話型モードとは異なる動作をするのはなぜですか?

午後ずっと試してみましたが、うまくいかないようです。

明らかに説明があるでしょう。

あなたが提供できるすべての情報に感謝します。

PS:PHPコードの基本は次のとおりです。

$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock, '0.0.0.0', 2000);
for (;;) {
  socket_recvfrom($sock, $cmd, 1024, 0, $ip, $port);
  echo "command is $cmd";
  $reply = process($cmd);
  echo "reply is $reply";
  socket_sendto($sock, $reply, strlen($reply), 0, $ip, $port);
}

ncを使用してインタラクティブにテキストを入力するときは、CTRL-Dを押してパケットを切り離すことができます。シェルスクリプトで同じことを行う場合:

printf 'command1\0014commandd2\0014'| nc -u host port

...これらのコマンドはすべて1つのコマンドとして表示されます。

PHPコードのパケットサイズを5に減らしてから20バイト長のデータを送信すると、データは切り捨てられ分離されません。

もしかしたらバッファリング問題かもしれないとオンラインでも用意しました。私は以下を使用しようとしています:

stdbuf -oL -eL cat FILE | nc -u host port 

...しかし、驚くべきことに、これもあまり違いはありませんでした。

最後に、そうすれば次のような事実を発見しました。

for x in command1 command2; do 
  echo $x 
  sleep 1
done | nc -u host port

…すべてが計画通りに行われました。サーバーは最初のコマンドを受け取り、次に2番目のコマンドを受け取ります。

本当に不明なのは睡眠1が効果がある理由です。取り出すと失敗します。上記は、すべてのエコーをncに送信するよりも確かに優れています。

ベストアンサー1

l0b0は問題を解決しましたが、他のものに対する答えは次のとおりです。

もちろん、ファイルの内容を包んで各行をnc:に送ることもできますが、for x in $(cat <file>); do echo $x | nc -u host port; doneそれは完全な無駄です。私はNCへの1つの関係がほしいと思います。多くはありません。

1)実際にファイルの行を送信せずにスペースで区切られた内容を送信します。空白は改行、タブ、または空白にすることができます(IFSを変更していない場合)。これらのコマンドは、「コマンド」の理解が1つの単語に限定されている場合にのみ同じですが、通常、ほとんどのUnix(y)コマンドは複数の単語です。これらの単語はシェルパス名拡張(しばしば「globbing」とも呼ばれます)のために処理されるため、に値が含まれている場合は?*[..]ファイル$xの値と異なる場合があります。

2)UDPは接続がなく、まったく接続がないため、接続は「無駄」になりません。たぶんあなたは望んでいないという意味かもしれません実行手続き型nc(ローカル)

対話型モードが非対話型モードとは異なる動作をするのはなぜですか?

入力する端末Unixでは通常、一度に1行ずつ処理します。プログラム(ここではnc)が操作を実行するときにreadEnter(またはそれに対応するキー)を押してから、次のように入力するまで、必要な数の文字を入力するのを待ち、オプションで編集します。 (ncパケットとして送信するため)プログラムに渡されます。 (プログラムのバッファが小さすぎない限り、適切な部分だけが送信され、残りの部分は次の読み取りを待ちます。)オプションでこの機能をオフにすることができ、各文字(またはプログラムによって生成された文字グループ)の単一キー入力) - などのプログラムで使用できるように、いくつか(ファンクションキーなど)を個別に提供できますが、それほどvi明確ではありませんbash。正式にはこう呼ばれる。「正規」および「非正規」モードしかし、歴史的に非標準パターンは「生」として記述され、標準パターンは「調理済み」パターンとして説明されてきた。

他の種類のファイル(パイプを含む)からデータを読み取ると、改行(改行など)は無視され、バッファに適合するすべての内容が読み取られます。ユーザーには複数行が含まれています。

ncを使用してインタラクティブにテキストを入力するときは、CTRL-Dを押してパケットを切り離すことができます。シェルスクリプトで同じ操作を実行すると、printf 'command1\0014commandd2\0014'| nc -u host portすべてのコマンドが1つのコマンドとして表示されます。

3)端末のControl-Dは特別です。より正確には、eofターミナルドライバで設定されているように設定された文字(通常はControl-Dですが変更可能)が特別です。入力したとおりこれプログラムが文字を読み込んでいる間、戻りを待つか、データに control-D を含めずに読み取りが終了します。ファイルに control-D が表示される場合、対応する文字コードは特別ではありません。

4)そしてあなたが生成するキャラクターはとにかくCtrl-Dではありません。 Control-Dは、\004多くのバージョンechoや他の状況で使用される\x048進表記です。 Control-AはSTXとも呼ばれ、Unixでは実際には使用されません(\001複数の仮想端末ウィンドウ間の切り替えを制御するために使用されるプログラムを除く)。screen

もしかしたらバッファリング問題かもしれないとオンラインでも用意しました。私は以下を試してみました。stdbuf -oL -eL cat FILE | nc -u host port...しかし、驚くべきことに、これも何の違いもありませんでした。

5)stdbufCライブラリの「stdio」ルーチンにのみ影響し、catテキストとテキストではなく「バイナリ」データの両方を処理するように設計されているため、これらのルーチンは使用できません。最も便利なテストシステム(CentOS6)では、straceGNU-coreutils-8.4がcat影響を受けていないことを確認しましたが、stdbuf他の実装が影響を受ける可能性があることを除外することはできません。sed '' file; grep '' file; awk 1 file私が確認したように、テキストを行単位で処理するように設計されたプログラムを使用するとstdbuf -oL違いが発生します。

しかし、それはあなたが望む変化をもたらさないかもしれません。パイプにラインを追加するライタープログラムとncそれを読み書きすることとの間に競合状態がある可能性があり、ビルダーがより速い場合は、複数の行を1つの発信パケットにまとめます。

最後に、私はこれを行うと、すべてfor x in command1 command2; do echo $x; sleep 1; done | nc -u host portが計画通りに進むことに気づきました。サーバーは最初のコマンドを受け取り、次に2番目のコマンドを受け取ります。

本当に不明なのは睡眠1が効果がある理由です。 ...

6)これは競争条件を防ぎます。シェルがパイプに1行を書き込むたびに、シェルが次に書き込むnc前にそれを読み書きする時間は確かにあります。

おすすめ記事