Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

basic chat system on perl under linux

Tags:

linux

chat

perl

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

  1. I could not understand how to keep checkFile function always active (like multiprocession) to continuously check for new messages

  2. This problem occurs when I'm trying to write a new message that will be appended into the chatlog. The Interpreter waits for my input on the line my $newMessage = <STDIN>;, but, what if someone writes a new message? it will not be shown until he press enter... how to void that?

    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;
            }
        }
    }
    
like image 250
PYPL Avatar asked Nov 10 '22 01:11

PYPL


1 Answers

First:

  • don't use echo within a perl script. It's nasty to shell escape when you've got perfectly good IO routines.

  • using cat to read files is about as nasty as using 'echo'.

  • reading <STDIN> like that will be a blocking call - which means your script will pause.

  • but that's not as bad as it sounds, because otherwise you're running a 'busy wait' loop which'll repeatedy cat the file. This is a very bad idea.

  • You're assuming writing a file like that is an atomic operation, when it's not. You'll hit problems with doing that too.

What I would suggest you do it look at IO::Handle and also consider using flock to ensure you've got the file locked for IO. You may also wish to consider File::Tail instead.

I would actually suggest though, you want to consider a different mode of IPC - as 'file swapping' is quite inefficient. If you really want to use the filesystem for your IO, you might want to consider using a FIFO pipe - have each 'client' open it's own, and have a server reading and coalescing them.

Either way though - you'll either need to use IO::Select or perhaps multithreading, just to swap back and forth between reading and writing. http://perldoc.perl.org/IO/Select.html

like image 85
Sobrique Avatar answered Nov 15 '22 05:11

Sobrique