Java网络编程从入门到精通(25):创建ServerSocket对象
2009-09-22 00:00:00 来源:WEB开发网假设第2行和第6行的代码是Thread.sleep(3000),这将使程序延迟3秒。那么在这3秒内,程序不会执行accept方法,因此,这段程序只是将端口绑定到了1234上,并未开始接收客户端请求。如果在这时一个客户端向端口1234发来了一个请求,从理论上讲,客户端应该出现拒绝连接错误,但客户端却显示连接成功。究其原因,就是这节要讨论的请求队列在起作用。
在使用ServerSocket对象绑定一个端口后,操作系统就会为这个端口分配一个先进先出的队列(这个队列长度的默认值一般是50),这个队列用于保存未处理的客户端请求,因此叫请求队列。而ServerSocket类的accept方法负责从这个队列中读取未处理的客户端请求。如果请求队列为空,accept则处于阻塞状态。每当客户端向服务端发来一个请求,服务端会首先将这个客户端请求保存在请求队列中,然后accept再从请求队列中读取。这也可以很好地解释为什么上面的代码在还未执行到accept方法时,仍然可以接收一定数量的客户端请求。如果请求队列中的客户端请求数达到请求队列的最大容量时,服务端将无法再接收客户端请求。如果这时客户端再向服务端发请求,客户端将会抛出一个SocketException异常。
ServerSocket类有两个构造方法可以使用backlog参数重新设置请求队列的长度。在以下几种情况,仍然会采用操作系统限定的请求队列的最大长度:
backlog的值小于等于0。
backlog的值大于操作系统限定的请求队列的最大长度。
在ServerSocket构造方法中未设置backlog参数。
下面积代码演示了请求队列的一些特性,请求队列长度通过命令行参数传入SetRequestQueue。
package server;
import java.net.*;
class TestRequestQueue
{
public static void main(String[] args) throws Exception
{
for (int i = 0; i < 10; i++)
{
Socket socket = new Socket("localhost", 1234);
socket.getOutputStream().write(1);
System.out.println("已经成功创建第" + String.valueOf(i + 1) + "个客户端连接!");
}
}
}
public class SetRequestQueue
{
public static void main(String[] args) throws Exception
{
if (args.length == 0)
return;
int queueLength = Integer.parseInt(args[0]);
ServerSocket serverSocket = new ServerSocket(1234, queueLength);
System.out.println("端口(1234)已经绑定,请按回车键开始处理客户端请求!");
System.in.read();
int n = 0;
while (true)
{
System.out.println("<准备接收第" + (++n) + "个客户端请求!");
Socket socket = serverSocket.accept();
System.out.println("正在处理第" + n + "个客户端请求");
Thread.sleep(3000);
System.out.println("第" + n + "个客户端请求已经处理完毕!>");
}
}
}
更多精彩
赞助商链接