我试着写一些基本的聊天系统只是为了学习perl。我试图将聊天记录变成1个文件,如果它出现在chatlog.dat
文件中,则打印新消息,所以我写了一个几乎完全相同的功能,但我有一些问题,不知道如何解决它们。
所以现在我有2个问题!
我无法理解如何保持checkFile
功能始终处于活动状态(如多处理)以持续检查新消息
当我尝试编写将附加到聊天记录中的新邮件时,会出现此问题。口译员在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;
}
}
}
答案 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();