3.4 监听连接──listen()
此调用用于面向连接服务器,表明它愿意接收连接。listen()需在accept()之前调用,其调用格式如下:
int PASCAL FAR listen(SOCKET s, int backlog);
参数s标识一个本地已建立、尚未连接的套接字号,服务器愿意从它上面接收请求。backlog表示请求连接队列的最大长度,用于限制排队请求的个数,目前允许的最大值为5。如果没有错误发生,listen()返回0。否则它返回SOCKET_ERROR。
listen()在执行调用过程中可为没有调用过bind()的套接字s完成所必须的连接,并建立长度为backlog的请求连接队列。
调用listen()是服务器接收一个连接请求的四个步骤中的第三步。它在调用socket()分配一个流套接字,且调用bind()给s赋于一个名字之后调用,而且一定要在accept()之前调用。
有关listen()的详细描述参看5.2.13。
2.3节中提到钥纪纪户/服务器模式中,有两种类型的服务:重复服务和并发服务。accept()调用为实现并发服务提供了极大方便,因为它要返回一个新的套接字号,其典型结构为:
int initsockid, newsockid;
if ((initsockid = socket(....)) < 0)
error(“can’t create socket”);
if (bind(initsockid,....) < 0)
error(“bind error”);
if (listen(initsockid , 5) < 0)
error(“listen error”);
for (; {
newsockid = accept(initsockid, ...) /* 阻塞 */
if (newsockid < 0)
error(“accept error“);
if (fork() == 0){ /* 子进程 */
closesocket(initsockid);
do(newsockid); /* 处理请求 */
exit(0);
}
closesocket(newsockid); /* 父进程 */
}
这段程序执行的结果是newsockid与客户的套接字建立相关,子进程启动后,关闭继承下来的主服务器的initsockid,并利用新的newsockid与客户通信。主服务器的initsockid可继续等待新的客户连接请求。由于在Unix等抢先多任务系统中,在系统调度下,多个进程可以同时进行。因此,使用并发服务器可以使服务器进程在同一时间可以有多个子进程和不同的客户程序连接、通信。钥纪纪户程序看来,服务器可以同时并发地处理多个客户的请求,这就是并发服务器名称的来由。
面向连接服务器也可以是重复服务器,其结构如下:
int initsockid, newsockid;
if ((initsockid = socket(....))<0)
error(“can’t create socket”);
if (bind(initsockid,....)<0)
error(“bind error”);
if (listen(initsockid,5)<0)
error(“listen error”);
for (; {
newsockid = accept(initsockid, ...) /* 阻塞 */
if (newsockid < 0)
error(“accept error“);
do(newsockid); /* 处理请求 */
closesocket(newsockid);
}
重复服务器在一个时间只能和一个客户程序建立连接,它对多个客户程序的处理是采用循环的方式重复进行,因此叫重复服务器。并发服务器和重复服务器各有利弊:并发服务器可以改善客户程序的响应速度,但它增加了系统调度的开销;重复服务器正好与其相反,因此用户在决定是使用并发服务器还是重复服务器时,要根据应用的实际情考网考网来定。
|