socket编写聊天室服务器程序
上一篇 / 下一篇 2008-12-04 12:48:24 / 个人分类:perl
- 文件版本: V1.0
- 开发商: 本站原创
- 文件来源: 本地
- 界面语言: 简体中文
- 授权方式: 免费
- 运行平台: Win9X/Win2000/WinXP
Socket简易编程:
,D7F[_I9?~e;P0
^^5cRH3JG4P0
-en _0IC1Y0use IO::Socket;
W2}c$Du6h0
_(A@r$~8g1f.j?&\0my $listening_socket =51Testing软件测试网 l@9B
SAD ?
IO::Socket::INET->new(Proto => 'tcp',51Testing软件测试网FAf:Y'gNF
LocalPort => 2323,51Testing软件测试网h]YYG_
Listen => 1,51Testing软件测试网(qi(H1ZO8W#P,MT
Reuse => 1) or die $!;
4r
pA6O/p"s0所有参量的含义:
lWhG%]0Proto: 定义网络所用的协议 - 在这里我们用的是TCP. 在internet上通常有两种协议用得比较广泛 - TCP 和 UDP. TCP适用于稳定的连接,可以重新发送丢失的数据包,而UDP用于那些不用重发数据包的场合(如实时音频数据流).
7S#x5eI~(G"_0LocalPort: 定义连接的端口号.51Testing软件测试网:LBi*K(Z@z
Listen: 我们将**来自其它计算机的连接,而不是自己建立一个连接.所以用户要先telnet到端口2323,然后运行了聊天服务程序的计算机来建立连接.51Testing软件测试网E"MEb[E:n]
Reuse: 这个选项意思是如果我们"杀掉"聊天服务程序然后再重新启动,将能够马上重新使用原来的端口,而不用等待以前那个连接完全结束.51Testing软件测试网htB%wH(NG9bt
我们正等待某个连接的到来.... 一个连接到来以后,我们需要accept这个新的连接:51Testing软件测试网8f:e!Sy;\+KL
$socket = $listening_socket->accept;51Testing软件测试网'`;Fg%sP*~%yY(e
一旦我们建立了一个连接,我们可以发送一些文字给这个用户(还不完全是,请看本文的结尾部分):51Testing软件测试网l%t6Y
J7\-C
i}j*C
$socket->send("hellorn") or print "connection closed at other endn";
k
j'l2uNZ4J"E0我们也可以接收用户发来的信息:51Testing软件测试网+k*t.d}/o
E%p$l
$socket->recv($line, 80);51Testing软件测试网r3nJ)l5v0|,BdA$y0u.i
if($line eq "") {51Testing软件测试网[CkPU+c9J
print "connection closed at other endn";51Testing软件测试网F:OOs)A_
}51Testing软件测试网rt^0L.Y8_
最后我们完成了连接,可以关闭它:
$caJ
w5G_0$socket->close;51Testing软件测试网G6I1W/?eI*X#i
大部分程序只在一个时刻处理一个用户.如果用户还没有准备好,程序就没有什么好做的.所以Perl程序没有从<stdin>读到什么东西,它就停下来等待直到用户准备好. (这叫blocking I/O.)
w$Lm Rl0这种方式不能用于聊天服务程序,用户不可能排着队来.一个用户可能离开去喝些咖啡,但其它用户还在拼命地敲打键盘(聊天),服务程序还得处理他们的信息.
Q5~;{(a"oFM~Hn"zX0解决这个问题的一个办法是为每个用户创建一个入口(entity),或者用fork()创建另外一个进程,或者用多线程编程方法(遗憾地是Perl还用不了).这样系统就可以为多个用户服务, 但每个用户有他自己的入口(entity)等待他输入命令. 但是进程的系统开销比较大,如果很多用户登录的话,系统资源很快会变得不足.最好是用一个进程来处理所有人的请求.
7s]g(m6k@{D'k0我们真正需要的是要知道谁正在等待服务,必须马上处理(除非没有一个人想聊天).这就是select()函数所要做的.51Testing软件测试网-FW%Ac'|]
象socket函数一样,select()曾经也是很难用,所以大多数程序员都尽量避免使用它. 但Perl给它加了一个面向对象编程的包装,叫做IO::Select,使得使用非常简单.
(Al6DPhr'[|+n Q0假设我们要等待两个sockets, $thing1 and $thing2. 首先我们创建一个包含两个socket的select()对象:
-Yv`T:Hnd0$select = IO::Select->new($thing1,$thing2);
8KCR1LEF8d:l0下一步,当我们需要知道谁有数据要处理时,我们就查询select对象:51Testing软件测试网QM+w}5X @
my @ready = $select->can_read;51Testing软件测试网HF~l)x#kr5s6y
这个调用将等待直到$thing1或$thing2中任何一个准备好, 它将返回一个包含socket的数组. (如果它们都准备好了,@ready将包含两个socket.) 一旦有了准备好的socket, 我们一个一个地读取数据找出它们发送的是是什么:51Testing软件测试网 BE/HN^3fD]A!Z
for $socket (@ready) {