DEV Community

Cover image for Developing A Game Engine with Perl: Part 6 - A Colourful Telnet Server
Shawn Holland
Shawn Holland

Posted on • Updated on

Developing A Game Engine with Perl: Part 6 - A Colourful Telnet Server

I'll stop reminding you that... I DO NOT KNOW WHAT I AM DOING.

If you want to start reading from the beginning. Check out the first article in this series

What is ANSI Game Engine?

Well, at it's core, ANSI Game Engine is a very colourful and interactive telnet server.

Why telnet!?

I know, right!? I still ask myself the same question today, but at this point, I'm kinda committed. Initially, it all came down to my decision NOT to code the client side. I looked into it, and it just wasn't something I wanted to do. And honestly, it seemed too far outside my comfort level with Perl. I feel much more comfortable, and interested in, working with server side code, as may be true for other Perl dev's out there. That's where Perl is quite prolific. Since I was going with ANSI graphics, they are best known these days, for me at least, to be used in telnet/terminal clients and BBS's, which are mainly telnet based now. This being said, it wasn't long searching google before I came across SyncTERM. SyncTERM is, in my opinion, the best available choice for cross-platform rendering of ANSI graphics over telnet. I've tried many different clients, on Mac, Windows, and Linux. SyncTERM works the most consistent across these platforms, it's been around for a long time and is still actively being developed. So telnet it is!

Telnet.... Fork me...

The engine has to be multiplayer. Depending on the specific game requirements, this does not necessarily mean players interacting with each other, but at least having multiple players connected at the same time to the same server. This is a minimum initial requirement. To me, this is a great opportunity to work with Fork. I really like the idea of creating multiple processes with fork that can interact with each other. This is an area I have little experience with and a great opportunity to learn.

Have you heard of Perl's CPAN?

If you are a Perl dev, obviously yes. If you code in another language, perhaps you've heard of it. Comprehensive Perl Archive Network, or CPAN, is Perl's repository of code modules. If you want to do something, chances are someone has already made a module for that. As of writing this article, CPAN currently has 208,034 Perl modules written by 14,179 authors. It's absolutely amazing!

This is where I found the modules to develop a telnet server. A forking telnet server, can you believe it? Fork yah! Okokok.... I'll stop making that joke, I promise!

Let's get to coding!

The first step was to get a telnet server that could accept multiple simultaneous connections. I read up on how to make a telnet server with Perl and from that reading I quickly learned about IO::Socket::INET. It wasn't long after I had working code for a telnet server!

use strict;
use warnings;
use IO::Socket::INET;
print "\nBEGIN\n";

print "Setting up listen socket\n";
my $socket = new IO::Socket::INET (
    LocalHost => '192.168.1.15',
    LocalPort => '27777',
    Proto => 'tcp',
    Listen => SOMAXCONN,
    ReuseAddr => 1
);

my $player_socket;
my $player_data;

print "Waiting for connection ...\n";
while(1) {

    next unless $player_socket = $socket->accept();
    print "Incomming Connection!\n";

    my $player_address = $player_socket->peerhost();
    my $player_port    = $player_socket->peerport();

    my $response = "Player Connection Info: $player_address : $player_port. ";
    print "$response\n";

    $response .= "Press Any Key To Disconnect...\n";
    $player_socket->send($response);

    print "Waiting for player to press a key and disconnect...\n";
    while ($player_socket->connected()) {

        $player_socket->recv($player_data, 1024);
        if ($player_data) {
            print "Player Disconnecting $player_address : $player_port\n";
            $socket->close();
            print "Player Disconnected\n";
            last;
        }

    }
    last;
}
print "Good Bye!\n";
exit;
Enter fullscreen mode Exit fullscreen mode

Running this code and connecting with SyncTERM shows:

localhost:~ # perl telnet_server.pl 

BEGIN
Setting up listen socket
Waiting for connection ...
Incomming Connection!
Player Connection Info: 192.168.1.9 : 55414. 
Waiting for player to press a key and disconnect...
Player Disconnecting 192.168.1.9 : 55414
Player Disconnected
Good Bye!

Enter fullscreen mode Exit fullscreen mode

Image description

I read my Linux OpenSuSE server's man page for listen(2), and the best I can understand is that the value for SOMAXCONN in Listen => SOMAXCONN will allow me to have up to 4096 connections!? I think this is correct. It says the value can be found in /proc/sys/net/core/somaxconn and doing a cat of that file shows 4096.

localhost:~ # cat /proc/sys/net/core/somaxconn 
4096

Enter fullscreen mode Exit fullscreen mode

Now we just need to fork!

This process turned out to be a bit more difficult to understand (for me) and a few more lines of code then did the telnet portion. I'll pick up from here in the next article.

Have you done any telnet programming before? If so, what modules have you found useful? (CPAN or otherwise)

If you have any suggestions or comments please share constructively. Also please visit our social media pages for lots of fun videos and pictures showing the game engine in action.

ANSI Game Engine on Instagram
ANSI Game Engine on Facebook

Prev << Part 5 - 32bit -> 64bit & Perl's Storable
Next >> Part 7 - Fork

Cheers!
Shawn

Discussion (0)