第三页 切莫空等

by Brian Slesinsky

大多数程序在同一时刻只能对一名用户进行操作。如果用户尚未准备好,程序便无所事事。所以当Perl程序从<STDIN>中读取数据而且用户没有键入信息时,它就会停止,直到用户准备就绪时再继续执行。(这种情况称作输入输出堵塞。)

但这在交谈服务器上行不通,因为用户们并非轮流进行操作。一位用户可能刚刚离开去喝咖啡,而其余的人还在输入信息,服务器必须传送他们的信息。

此问题的一个解决方法是为每个用户生成一个机构,这可以通过使用fork( )产生另一个进程或采用多线编程(很遗憾,Perl尚没有此功能)来实现。系统可支持多用户,但是每位用户仍然有自己的机构,这些机构等待来自本用户的命令。

然而,产生新进程的“花费”太大,所以,当越来越多的用户登录在交谈服务器上时,这种方法的效率会大幅度下降。最好能让一个进程处理所有用户的请求。我们真正需要的是找出哪位用户已准备就绪,而不是盲目傻等。(除非没人要交谈)。Select( ) 可以完成此项工作。

和接口函数不同的是,一般来说Select( ) 难度较大,不易使用,所以多数程序员都会避免和它打交道。但是Perl给它装上了名为IO::select的一个面向对象的外套,使它较易被人们接受。

假定我们希望等待两个接口,$thing1 $thing2。首先我们生成一个包含这两个接口的Select( )对象:

$select=IO::Select->new($thing1,$thing2);

以后,无论何时我们想要了解谁将发来数据,只需询问这个Select对象即可:

my @ready=$select->can_read;

$thing1$thing2都没有准备好时,这个调用会一直等候下去。如果有一个接口准备就绪,调用就返回包含此接口的数列。(如果两个接口都准备就绪,@ready将包含两个接口。)

一旦有接口准备就绪,我们就要逐个读取它们发来的数据:

for $socket(@ready) {

$socket->recv($line,80);

if($line eq ) {die ?/FONT>they hung up on me?/FONT>;}

print ?/FONT>someone sent $line. Sending it back.\n?/FONT>;

$socket->send($line) or die ?/FONT>hey,where did they go??/FONT>;

}

Page 1: How to Write a Chat Server
Page 2: Socket Programming the Easy Way
Page 3: We Don?/FONT>t Wait for Nobody
Page 4: The Echo Chamber
Page 5: Now Broadcasting
Page 6: Keeping Track of Where You Were
Page 7: What?/FONT>s Left?


Brian Slesinsky is a former HotWired engineer. He left the company to work full-time on his death ray.