jgallagher has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to learn socket programming just for the heck of it, but there are a few things I'm just not seeing. In the following script, I'm trying to log the commands issued (via telnet) to this server. It creates the logfile, but it's always empty. Also, it does not process the if ($_ eq "quit") {} block correctly. Thanks in advance for any tips.
#!/usr/bin/perl -w use strict; use IO::Socket; my $host = 'localhost'; my $port = 9000; my $client; my $listen = new IO::Socket::INET->new( Proto => 'tcp', LocalPort => $port, Reuse => 1, Listen => 5, ) or die "Can't start server"; while ($client = $listen->accept()) { open OUT, ">>/home/john/perl/daemonlog" or die "Can't open OUT: $! +\n"; while (<$client>) { chomp; print $client "Thank you for your command: $_\n"; print OUT $_; if ($_ eq "quit") { close OUT; close $client; } } } close $listen;

Replies are listed 'Best First'.
Re: File I/O while using Sockets?
by chromatic (Archbishop) on Nov 22, 2000 at 04:43 UTC
    If your $_ comparison doesn't work, that usually indicates that it doesn't hold what you expect.
    print $client "Thank you for your command: ->$_<-\n"; print OUT "->$_<-\n";
    In my testing, I saw some spurious \r (carriage return) characters -- that may have been due to my use of a telnet client. A simple tr/\r//d; before the chomp fixed it for me.
Re: File I/O while using Sockets?
by Fastolfe (Vicar) on Nov 22, 2000 at 04:44 UTC
    If you're using 'telnet' to connect to port 9000, be aware that telnet will interpret your newlines as "\x0d\x0a", not a straight Perl \n. Thus, chomp will only rid you of the "\x0a" (what \n evaluates to under Unix, as in $/). Try either setting $/ to "\x0d\x0a" while processing data from the socket like that, use chop twice, or just use this regexp: s/\x0d\x0a$//;

    When in doubt, I've been known to simply do this when I don't know how the lines end: s/[\r\n]+$//;

    In addition, your print statement to OUT doesn't have a trailing newline, so your log file doesn't have an end-of-line to act on (stdio buffering does this, I believe). That's probably why you aren't seeing any of this ending up in the log file.

      Thanks, that did it. Just to check, it won't produce any funky side-effects to chomp; after the regexp to rid any newlines from any non-telnet clients, will it?
        See the documentation for chomp. It only affects a string if there's the value of $/ at the end. It's "safe" like that.
        Nope. =)

        --
        $you = new YOU;
        honk() if $you->love(perl)

Re: File I/O while using Sockets?
by a (Friar) on Nov 26, 2000 at 02:48 UTC
    I often try:
    if (/^\s*quit\s*$/i ) {
    instead of 'eq "quit"' as it lets Quit and QUIT work, along w/ " quit " (note worthless whitespace) for those non-typists out there.

    Yes, the \s*'s help; it won't quit on "I quit" that way. YMMV

    Not sure why you open|close OUT each time, if its a appending log file, but I've seen (on Solaris, for instance) that my output doesn't get flushed properly if the close isn't executed (e.g. you have Ctrl-C to kill the server because 'quit' isn't working) and I get zero byte log files. Move them outside the accept loop and add a 'marker' print stmt, that puts the date and the client IP into the log file.

    You may want to look at the cookbook/Camel and add a SIG handler that'll close OUT for INT/HUPs etc. If you can make sense of that, your socket programming knowledge will have gone forward another level.

    a