失效链接处理 |
ServerSocket用法 PDF 下载
本站整理下载:
提取码:syrm
相关截图:
主要内容:
第 3 章 ServerSocket 用法详解
在客户/服务器通信模式中,服务器端需要创建监听特定端口的 ServerSocket,
ServerSocket 负责接收客户连接请求。本章首先介绍 ServerSocket 类的各个构造方法,以及成
员方法的用法,接着介绍服务器如何用多线程来处理与多个客户的通信任务。
本章提供线程池的一种实现方式。线程池包括一个工作队列和若干工作线程。服务器程
序向工作队列中加入与客户通信的任务,工作线程不断从工作队列中取出任务并执行它。本
章还介绍了 java.util.concurrent 包中的线程池类的用法,在服务器程序中可以直接使用它们。
3.1 构造 ServerSocket
ServerSocket 的构造方法有以下几种重载形式:
l ServerSocket()throws IOException
l ServerSocket(int port) throws IOException
l ServerSocket(int port, int backlog) throws IOException
l ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException
在以上构造方法中,参数 port 指定服务器要绑定的端口(服务器要监听的端口),
参数backlog指定客户连接请求队列的长度,参数bindAddr 指定服务器要绑定的IP地址。
3.1.1 绑定端口
除了第一个不带参数的构造方法以外,其他构造方法都会使服务器与特定端口绑
定,该端口由参数 port 指定。例如,以下代码创建了一个与 80 端口绑定的服务器: ServerSocket serverSocket=new ServerSocket(80);
如果运行时无法绑定到 80 端口,以上代码会抛出 IOException,更确切地说,是抛
出 BindException,它是 IOException 的子类。BindException 一般是由以下原因造成的:
l 端口已经被其他服务器进程占用;
l 在某些操作系统中,如果没有以超级用户的身份来运行服务器程序,那么操
作系统不允许服务器绑定到 1~1023 之间的端口。
如果把参数 port 设为 0,表示由操作系统来为服务器分配一个任意可用的端口。
由操作系统分配的端口也称为匿名端口。对于多数服务器,会使用明确的端口,而不 会使用匿名端口,因为客户程序需要事先知道服务器的端口,才能方便地访问服务器。
在某些场合,匿名端口有着特殊的用途,本章 3.4 节会对此作介绍。
PDF 文件使用 "pdfFactory Pro" 试用版本创建 àwww.fineprint.cn
56 Java Netword Programming
3.1.2 设定客户连接请求队列的长度
当服务器进程运行时,可能会同时监听到多个客户的连接请求。例如,每当一个
客户进程执行以下代码:
Socket socket=new Socket(www.javathinker.org,80);
就意味着在远程 www.javathinker.org 主机的 80 端口上,监听到了一个客户的连接
请求。管理客户连接请求的任务是由操作系统来完成的。操作系统把这些连接请求存 储在一个先进先出的队列中。许多操作系统限定了队列的最大长度,一般为 50。当队
列中的连接请求达到了队列的最大容量时,服务器进程所在的主机会拒绝新的连接请
求。只有当服务器进程通过 ServerSocket 的 accept()方法从队列中取出连接请求,使队
列腾出空位时,队列才能继续加入新的连接请求。
对于客户进程,如果它发出的连接请求被加入到服务器的队列中,就意味着客户
与服务器的连接建立成功,客户进程从 Socket 构造方法中正常返回。如果客户进程发
出的连接请求被服务器拒绝,Socket 构造方法就会抛出 ConnectionException。
ServerSocket 构造方法的 backlog 参数用来显式设置连接请求队列的长度,它将覆
盖操作系统限定的队列的最大长度。值得注意的是,在以下几种情况中,仍然会采用 操作系统限定的队列的最大长度:
l backlog 参数的值大于操作系统限定的队列的最大长度;
l backlog 参数的值小于或等于 0;
l 在 ServerSocket 构造方法中没有设置 backlog 参数。 以下例程 3-1 的 Client.java 和例程 3-2 的 Server.java 用来演示服务器的连接请求队
列的特性。
例程 3-1 Client.java
import java.net.*;
public class Client {
public static void main(String args[])throws Exception{
final int length=100;
String host="localhost";
int port=8000;
Socket[] sockets=new Socket[length];
for(int i=0;i<length;i++){ //试图建立 100 次连接
sockets[i]=new Socket(host, port);
System.out.println("第"+(i+1)+"次连接成功");
}
Thread.sleep(3000);
for(int i=0;i<length;i++){
sockets[i].close(); //断开连接
}
}
}
PDF 文件使用 "pdfFactory Pro" 试用版本创建 àwww.fineprint.cn
Java Network Programming 57
第 3 章 ServerSocket 用法详解
例程 3-2 Server.java
import java.io.*;
import java.net.*;
public class Server {
private int port=8000;
private ServerSocket serverSocket;
public Server() throws IOException {
serverSocket = new ServerSocket(port,3); //连接请求队列的长度为 3
System.out.println("服务器启动");
}
public void service() {
while (true) {
Socket socket=null;
try {
socket = serverSocket.accept(); //从连接请求队列中取出一个连接
System.out.println("New connection accepted " +
socket.getInetAddress() + ":" +socket.getPort());
}catch (IOException e) {
e.printStackTrace();
}finally {
try{
if(socket!=null)socket.close();
}catch (IOException e) {e.printStackTrace();}
}
}
}
public static void main(String args[])throws Exception {
Server server=new Server();
Thread.sleep(60000*10); //睡眠 10 分钟
//server.service();
}
}
Client 试图与 Server 进行 100 次连接。在 Server 类中,把连接请求队列的长度设
为 3。这意味着当队列中有了 3 个连接请求时,如果 Client 再请求连接,就会被 Server
拒绝。下面按照以下步骤运行 Server 和 Client 程序。
(1)把 Server 类的 main()方法中的“server.service();”这行程序代码注释掉。这 使得服务器与 8 000 端口绑定后,永远不会执行 serverSocket.accept()方法。这意味着队
列中的连接请求永远不会被取出。先运行 Server 程序,然后再运行 Client 程序,Client
程序的打印结果如下:
第 1 次连接成功 第 2 次连接成功 第 3 次连接成功 Exception in thread "main" java.net.ConnectException: Connection refused: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(Unknown Source)
at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
|