recv() is deprecated on :utf8 handles

misimakansiserver: misima 漢詩平仄音韻分析デーモン,misimaserver: misima 旧仮名遣い・旧字変換デーモンのログに,いつのころからか次のようなエラーメッセージが出るようになっていた。

recv() is deprecated on :utf8 handles at /usr/local/lib/perl5/5.24/mach/IO/Socket.pm line 304.

機能的にはなんら支障が出ていないのでしばらく放置していたのだが,ちょっと気持ち悪いので対処することにした。

cpan perldelta によれば,Perl 5.23 あたりから,sysread(), syswrite(), recv(), send() について :utf8 ハンドルが廃止予定になったとのこと。

バークレイソケットインタフェースでクライアントと接続する際に,これまではクライアントのソケットディスクリプタ(ハンドル,通信路)に対し,binmode 関数で UTF-8 デコードするように指示していたのだが,これを行うとワーニングを発するようになっていたのだった。

とりあえず binmode:utf8 フラグをセットしてデコードするのをやめ,読み書きの前後に utf8::decode 関数(ストリームデータを Perl 内部で UTF-8 として処理できるようデコードする), utf8::encode 関数(Perl 内部データを UTF-8 にエンコードする)で変換操作を行うように改変した。コード主要部は以下のとおり。

while ($reqs-- > 0) {
    # クライアントからのリクエストを受信
    my $client = $listen_sock->accept() || last;
    my $readbuf;
    my $clip = $client->peerhost();
    my $ts = [gettimeofday] if ($sopts{'d'}); # タイマ
    print logtime() . " - $$ Chinese Verse Analysis Started.\n";
    # binmode $client, ":utf8";  # 削除
    defined ($client->recv($readbuf, $MAXLEN)) ||
        die logtime() . " - $$ recv error: $!\n";
    utf8::decode($readbuf);      # 追加: UTF-8受信データをデコード
 
    print logtime() . " - $$ Client: $clip; Received Text:\n$readbuf"
        if ($sopts{'d'});
    # クライアントからのデータをもとに処理を実行し,送信バッファにセット
    my $sendtext = kansi_main($readbuf);
 
    # 処理結果をクライアントに送信
    utf8::encode($sendtext);     # 追加: 送信データをUTF-8にエンコード
    print $client "$sendtext\n";
    $client->flush();
    $client->close();
    print tstrip($sendtext) if ($sopts{'d'});
    print logtime() . " - $$ Analysis for $clip Completed.\n";
    print logtime() . " - $$ Elapse: " . tv_interval($ts) . " sec.\n"
        if ($sopts{'d'});
}

これでワーニングを抑止できた。