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

I am writing a script that will have the ability to connect to a quake server and do some things with rcon. I have the communications part half done which brings me to this. Does anyone have any thoughts on why when I send a command to the server I don't get anything back from the server? I know the command gets to the server because I see it come over the log. However, the server doesn't communicate back to my script. Here is some code. Perhaps someone can find what I am doing wrong. On the other hand this maybe a quake-ism that I need to know something about to get this to work.

#!/usr/bin/perl # Jim Conner 4/30/2001 use IO::Socket; use strict; use Cwd; ################################################ my $rcon_passwd = "password"; my $peer_addr = "mybox.net"; my $peer_port = "27500"; ################################################ my $socket = IO::Socket::INET->new(PeerAddr => $peer_addr, PeerPort => $peer_port, Proto => 'udp') or die("Cannot open socket to $peer_addr on $peer_port\n"); # Could use "\xff\xff\xff\xff\x0" too my $prep = chr(255)x4; my $send = chr(0); #$socket->send("$prep rcon $rcon_passwd status\n"); print $socket "$prep rcon $rcon_passwd status\r"; while ( <$socket> ) { print; } print "done\n";

Bear in mind that I just started this code tonight and before I even started I didn't think I would be able to even talk to the server, however, here are the logs to show I am:

[Apr 30 02:48:10] Rcon from 192.168.100.14:1285:
        rcon (hidden) status
[Apr 30 02:48:10] net address      : 192.132.87.12:27500
[Apr 30 02:48:10] cpu utilization  :   0%
[Apr 30 02:48:10] avg response time: 1 ms
[Apr 30 02:48:10] packets/frame    :  0.82 (12)
[Apr 30 02:48:10] name               userid frags
[Apr 30 02:48:10]   address          rate ping drop
[Apr 30 02:48:10]   ---------------- ---- ---- -----
[Apr 30 02:48:10]
[Apr 30 02:51:49] Rcon from 192.168.100.14:1287:
        rcon (hidden) status
[Apr 30 02:51:49] net address      : 192.132.87.12:27500
[Apr 30 02:51:49] cpu utilization  :   0%
[Apr 30 02:51:49] avg response time: 1 ms
[Apr 30 02:51:49] packets/frame    :  0.82 (12)
[Apr 30 02:51:49] name               userid frags
[Apr 30 02:51:49]   address          rate ping drop
[Apr 30 02:51:49]   ---------------- ---- ---- -----
[Apr 30 02:51:49]
I have tried a few ways e.g.

 my @OPEN = $socket->send("line"); and

 my @OPEN = <$socket>; (which seems to be waiting on output from the server or at least it doesn't do anything once the request is sent ie the script sits there and looks at me funny, but I see the logs grow (tail -f) and no output comes to my perl script *shrug*). I know this can be accomplished since other programs do it (I have an mirc script that does it...and quake admin does it too) so I know I can do it with Perl....somehow. :)

I can at least finish the script, but I still do not get anything from the server. Is it me or quake.

*disclaimer* (: I am new to Perl and am even newer to socket programming. Please be gentle =P

TIA

----------
- Jim

Replies are listed 'Best First'.
Re: IO::Socket::INET, quake, and me...
by t0mas (Priest) on Apr 30, 2001 at 12:06 UTC
    I think the kkrcon program (a perl script) does exactly what you try to accomplish. Have you checked it out?

    Good luck and happy gaming.

    /brother t0mas
      I wouldv'e replied to the original node but I think the html was messed up.

      You may want to look at IO::Socket::INET. You are connecting using a UDP connection, but you are trying to communicate with it as if it was a TCP connection. Quake needs the UDP. To communicate with UDP, try the following:

      my $buffer = undef; $remote_sock->send("My stuff to send",0); $remote_sock->recv($buffer,4096,0); # SOCK, LEN, OFFSET # $buffer will now contain the response

      Hope that helps...

      my @a=qw(random brilliant braindead); print $a[rand(@a)];
      No! I didn't know it existed! But I will certainly check it out! Thank you very much. (I searched everywhere for this kind of script. I must not have used the correct search keywords)

      Thanks!

      ----------
      - Jim

Re: IO::Socket::INET, quake, and me...
by astanley (Beadle) on Apr 30, 2001 at 18:25 UTC
    Aside from checking a different script for what you are trying to do here is my USD $.02. the while ( <$socket> ) { function you've defined using <>'s to read the incoming line. AFAIK the brackets are waiting for a \n (carriage return) before executing the loop. I suggest putting some reading into syswrite and sysread to replace your print $socket and while (<$socket>) {. I've used them in a similar situation and they're quite easy to implement. Something like:
    syswrite($socket, "$prep rcon $rcon_passwd status\r");
    Is the equivalent of the print function and:
    while ( (sysread($socket, $incoming, 1024) != 0) { print $incoming; }
    Will replace your bracket implementation.

    -Adam Stanley
    Nethosters, Inc.
Re: IO::Socket::INET, quake, and me...
by HeatSeekerCannibal (Beadle) on Dec 07, 2007 at 17:45 UTC
    A bit late, but I'll offer whatever little help I can...

    I had a somewhat similar problem and it ended up being my client not sending a \n at the end of each message. I was able to send my messages, but the server didnt get them until I killed my client program.

    It seems that the newline is what IO::Socket::INET takes as the default input record separator (unless specified otherwise by changing $/...right?).

    Best of luck!

    Heatseeker Cannibal

      No, that has nothing to do with IO::Socket::INET. It has to do with <$sock> also known as $sock->readline(); which won't return until either $/ is read or end-of-file. Killing the client closes the socket which sends end-of-file (as would using shutdown).

      This is part of the reason one should normally not use <$sock> but instead should use sysread (or similar). Even if your protocol adds newlines on the end of each "packet", using <$sock> makes it hard to debug what broke when things go wrong.

      - tye