Perl中的基本网络聊天应用程序

时间:2015-09-22 22:11:18

标签: perl network-programming

我正在尝试在Perl中编写一个基本的网络聊天应用程序用于学习目的。我目前有一个服务器和客户端程序,几乎按照我的要求运行。多个客户端可以连接到服务器并向其发送消息。但是,我不确定如何将消息从一个客户端发送到另一个客户端,并希望在这里推进正确的方向。这是我到目前为止的代码,想法?

注意:这是我第一次尝试使用网络或使用Perl进行正确的项目,所以任何其他关于如何编写它的指导也将受到赞赏。

chat_server.pl

#!/usr/bin/perl -w
# chat_client.pl
use strict;
use IO::Socket::INET;

my $port            = shift or die "No port\n";
my $server          = shift or die "No server\n";
my $client_socket   = IO::Socket::INET->new(
        PeerPort    =>  $port,
        PeerAddr    =>  $server,
        Proto       =>  'tcp'
    ) or die "Can't create send socket: $!!\n";

my $child;

if($child = fork) {
    while(1) {
        sleep(1);
        print scalar <$client_socket>;
    }
}

die "fork failed!\n" unless defined $child;
print "Connected to $server:$port!\n";

do {
    print "> ";
    print $client_socket $_ if defined $_;
} while(<STDIN>);

print "Closing connection";
close $client_socket;

chat_client.pl

<script language="Javascript">
<!--
{
    var now = new Date();
    var h = now.getHours();
    var m = now.getMinutes();
    var s = now.getSeconds();
    if (hours < 7){timemsg = "Wakey wakey, Mr. Person. The time is: " + hours + ':' + minutes + ':' + seconds};
    if (hours > 6 && hours <12){timemsg = "Good morning, Mr. Person. The time is: " hours + ':' + minutes + ':' + seconds};
    if (hours > 11 && hours <18){timemsg = "Good afternoon, Mr. Person. The time is: " hours + ':' + minutes + ':' + seconds};
    if (hours >17){timemsg = "Good evening, Mr. Person. The time is: " hours + ':' + minutes + ':' + seconds};
    document.write(timemsg)};
// -->
</script>

1 个答案:

答案 0 :(得分:1)

单个客户端到单个服务器并不太困难 - 您正在使用的代码 - 有效地 - 创建1对1的关系。您的fork服务器专门与您的客户通话。

要获取在多个客户端之间传播(通过服务器)的信息,您将不得不变得更复杂 - 因为您有单独的进程,这些进程现在需要相互通信。这是一个足够大的问题,有关于它的perl文档的整个部分:perlipc

这实际上会大大增加代码的复杂性,因为您正在转向通信上的1对多关系,并且它们都将异步发生。

基于套接字的通信是进程间通信(IPC)的一种形式,您已经在这样做了。但是你的'问题'在于你从1到1的通信转移到1到多个通信。你需要能够进行广播,而这种通信方式并不能很好地支持。

我建议看看IO::Pipe - 我在这里有一些示例代码:How to extract data from Parallel::ForkManager in perl

然后使用IO::Selectcan_read异步判断管道中是否有任何数据。你可能需要一个管道数组 - 每个客户端一个 - 否则你可能会发生重复的并发事件。

E.g:

(来自IO::Pipe doc page:

 my $pipe = IO::Pipe->new();
if($pid = fork()) { # Parent
        $pipe->reader();
        while(<$pipe>) {
        ...
        }
    }
    elsif(defined $pid) { # Child
        $pipe->writer();
        print $pipe ...
    }

不幸的是,这里有一个小问题 - 您的管道将由分叉过程创建,但这反过来意味着您需要弄清楚如何处理管道数组并检查它们是否可读。< / p>

这意味着你不能再坐在while循环中接受套接字了 - 那些阻塞,所以你有消息排队直到另一个客户端连接(这真的不是你想要的) 。因此,您还需要再次使用select来检查是否有先准备好accept的内容。