6

ソケットから 4 つの符号なし整数を読み取る必要がある小さな Perl 学習プロジェクトを実行しようとしています。1 つ以上の整数を読み取ることができませんでした。掘り下げた後、解決策を見つけました。しかし、私が正しくしなかったことを理解する必要があります (そして、何冊かの Perl の本、perldocs などを調べても無駄でした)。

例 1: 成功したソリューション コード (オリジナル) は次のとおりです。以下の両方でソケット接続が成功したと仮定します。

{
  local $/ = \16; # make <> read in 16 bytes with one swoop.
  my @integers = unpack "IIII", <$sock>;
  print "numbers: @val\n";
}

例 2: 以下で試してみました。アンパックする前に入力を出力すると、整数が 1 つしか得られません。

my $input;
$sock->recv($input,16,0);
my @integers = unpack("IIII", $input);

具体的な質問:

  1. 例 1 の "$/" は一体何ですか? そして、STDINを読んだと思った<>はどのように「変化」しますか?
  2. 例 2 では、recv() がソケットから複数の整数を取り出さない理由はありますか? 私の理解 (perldoc による) では、"SIZE" パラメータのデフォルトは "bytes" で、整数は 4 バイトですか?

ヘルプ、ポインタなどをいただければ幸いです。ところで、「学習プロジェクト」は overthewire.org です。かなりクールなものです。

4

3 に答える 3

5

ソケットは TCP または UDP ですか?

recv<>/より下位のルーチンですreadline。多かれ少なかれrecv(2)システムコールに直接マップされます。ソケット データが 4 つの 4 バイト パケットとして到着するrecv場合、より大きなバッファが提供されていても、最初のパケットを確認するとすぐに戻ります。への最初の呼び出しの前に 4 つのパケットすべてが到着した場合recv()、すべてのデータを取得するか、1 つのデータのみを取得するかは、TCP と UDP のどちらであるかによって異なります。

TCP を使用している場合、パケットが飛行中にフラグメント化される可能性があります。16 バイトのペイロードで発生する可能性はほとんどありませんが、サーバーが一度に送信したことがわかっている場合でも、16 バイトのデータがすべて一度に表示されると想定しないことをお勧めします。通常、ネットワーク アプリケーションは着信データをバッファリングすることが期待されます。または、16 バイト レコードを$/ = \16.

<>この種の I/O の使用法よりも自然だと思うもう 1 つの可能性は、 readorsysread関数 (またはIO::Socketスーパークラスで定義されている OO の同等物) を使用することIO::Handleです。これらは長さの引数を取りますが、以前と同様に、バッファー全体が一度に満たされると想定しないでください。

于 2011-04-08T21:15:26.043 に答える
2

1)については

まあ、<>ソケットを含む任意のファイルハンドルを取ります。空のままにしておくことが慣例であり、その場合、ある種の適切なデフォルトの動作が想定されます。参照perldoc perlop(中を検索<>)。

特別な変数$/はレコードセパレータで、デフォルトは "\n" です。それを undef して、ファイル全体を一度に読み取ることができます (これは丸呑みと呼ばれます)。詳しくはこちらperldoc perlvarをご覧ください(\numberケースもあります)。

于 2011-04-08T19:49:57.643 に答える