linux下perl上的基本聊天系统

时间:2014-09-29 16:39:18

标签: linux perl chat

我试着写一些基本的聊天系统只是为了学习perl。我试图将聊天记录变成1个文件,如果它出现在chatlog.dat文件中,则打印新消息,所以我写了一个几乎完全相同的功能,但我有一些问题,不知道如何解决它们。 所以现在我有2个问题!

  1. 我无法理解如何保持checkFile功能始终处于活动状态(如多处理)以持续检查新消息

  2. 当我尝试编写将附加到聊天记录中的新邮件时,会出现此问题。口译员在my $newMessage = <STDIN>;行等待我的输入,但是,如果有人写了新消息怎么办?直到他按下进入才会显示...如何取消它?

    my ($sec,$min,$hour) = localtime();
    while(1){
        my $userMessage = <STDIN>;
        last if $userMessage eq "::quit";
        `echo "($hour:$min:$sec): $userMessage" >>chatlog.dat`;
    }
    
    sub checkFile{
        my $lastMessage = "";
        my $newMessage = "";
        while (1) {
            my $context = `cat chatlog.dat`;
            split(/\n/, $context);
            $newMessage = $_[$#_];
            if ($newMessage ne $lastMessage) {
                print $newMessage;
                $lastMessage = $newMessage;
            }
        }
    }
    

2 个答案:

答案 0 :(得分:1)

首先:

  • 不要在perl脚本中使用echo。当你有完美的IO例程时,它很难逃脱。

  • 使用cat读取文件与使用“echo”一样令人讨厌。

  • 读取<STDIN>就像是一个阻塞调用 - 这意味着你的脚本会暂停。

  • 但这并不像听起来那么糟糕,因为否则你正在运行一个“忙等待”循环,它会重复cat文件。这是一个非常糟糕的主意。

  • 你假设写一个像原子操作的文件,当它不是时。你也会遇到这样的问题。

我建议您查看IO::Handle并考虑使用flock来确保您已为IO锁定文件。您可能还希望考虑使用File::Tail

我实际上建议你,你想考虑一种不同的IPC模式 - 因为'文件交换'是非常低效的。如果您真的想要为IO使用文件系统,您可能需要考虑使用FIFO管道 - 让每个“客户端”打开它自己的,并让服务器读取并合并它们。

无论哪种方式 - 你要么需要使用IO::Select,要么使用多线程,只需在阅读和写作之间来回切换。 http://perldoc.perl.org/IO/Select.html

答案 1 :(得分:0)

回答我自己的问题

sub checkFile{
    my $lastMessage = "";
    my $newMessage = "";
    my $userName = $_[0];
    while (1) {
        my $context = `cat chatlog.dat`;
        split(/\n/, $context);
        $newMessage = $_[$#_];
        if ($newMessage ne $lastMessage) {
            $newMessage =~ /^\(.+\):\((.+)\) (.+$)/;
            if ($1 ne $userName) { print "[$1]: $2";}
            $lastMessage = $newMessage;
        }
    }
}

my $userName = "Rocker";
my ($sec,$min,$hour) = localtime();
my $thr = threads -> create ( \&checkFile, $userName ); #Starting a thread to continuously check for the file update

while (1) {
    my $userMessage = <STDIN>; #STDIN will not interfere file checking
    last if $userMessage eq "::quit";
    `echo "($hour:$min:$sec):($userName) $userMessage" >>chatlog.dat` if $userMessage =~ /\S+/;
}

$thr -> join();