The basic chat system on perl under linux

I am trying to write a basic chat system to learn perl. I am trying to get chatlog into 1 file and print a new message if it appeared in the chatlog.dat file. So I wrote a function that does almost the same thing, but I have some problems and I don’t know how to solve them. So now I have 2 problems!

  • I could not figure out how to keep the checkFile function always active (e.g. multiprocession) to continuously check for new messages

  • This problem occurs when I try to write a new message that will be added to the chat log. The interpreter is waiting for my input on the line my $newMessage = <STDIN>; but what if someone writes a new message? it will not be displayed until it presses the enter button ... how to do it?

     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; } } } 
+5
source share
2 answers

Answering my question

 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(); 
0
source

At first:

  • do not use echo in perl script. This is unpleasant when you get excellent I / O routines.

  • using cat to read files is about as unpleasant as using echoes.

  • Reading <STDIN> similar to a blocking call, which means your script will stop.

  • but it’s not as bad as it seems, because otherwise you start a busy wait loop that repeats the cat file. This is a very bad idea.

  • You assume that writing such a file is an atomic operation when it is not. You will also encounter problems with this.

What I suggest you do is take a look at IO::Handle and also consider using flock to make sure the file is locked for I / O. You might want to consider File::Tail .

I would suggest, however, that you want to consider a different IPC mode - since file sharing is rather inefficient. If you really want to use the file system for your I / O, you may need to use the FIFO channel - each client must open its own, and the server will read and combine them.

In any case, you will either need to use IO::Select , or perhaps multithreading, just to swap between reading and writing. http://perldoc.perl.org/IO/Select.html

+1
source

Source: https://habr.com/ru/post/1203638/


All Articles