3

クライアントソケットでsend()を呼び出してフィールドを1つずつ返すperlサーバー側ソケットがあります。

コードが以下のような場合、クライアント側ですべてのフィールドを読み取ることに問題はありません。

while ($response = <$sock>) {
print "$response";
last if $response eq "END_OF_REQUEST";
}

しかし、クライアント側のコードが以下のような場合、ループに陥り、機能していません。

while(1) {      
$sock->recv($response, 1);
print "$response\n";    
last if $response eq "END_OF_REQUEST" ;
}

すべてのフィールドをクラブして、サーバー側で送信を 1 つだけ呼び出すことができることに同意します。しかし、2番目のアプローチの何が問題なのか知りたいです。2番目のアプローチでrecvのLENGTH引数を変更するとうまくいきますか?

ソケットに関する適切な理論的知識がなくても、直接実践するようになりました。お待ち頂きまして、ありがとうございます。

4

1 に答える 1

4

length 引数recv()は、受信したいメッセージの最大recv()長であり、それ以上の文字をバッファーに書き込むことはありません。(メッセージの残りの部分がどうなるかは、ソケットのタイプによって異なります。ストリーミング ソケットの場合は次のrecv()呼び出しで使用できますが、データグラム ソケットの場合は単純に破棄されます。)

したがって、$sock->recv($response, 1);最大で 1 文字のみを に書き込みます$response。明らかに、1 文字の文字列が と等しくなることはありません"END_OF_REQUEST"

簡単な解決策は、十分に大きな最大長を に渡してrecv()、メッセージが切り捨てられないようにすることです。


簡単なデモンストレーションを次に示します。

use strict;
use warnings;
use IO::Socket;

my ($rd, $wr) = IO::Socket->socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC)
    or die "socketpair: $!";
defined $wr->send("Hello, world!") or die "send: $!";
my $buf;
do {
    defined $rd->recv($buf, 9) or die "recv: $!";
    print qq(received: "$buf"\n);
} while ($buf !~ /!/);

これは出力されます:

received: "Hello, wo"
received: "rld!"
于 2013-01-21T18:34:27.740 に答える