Java 简明教程
Java - Networking
Advantages of Java Networking
-
Creating server-client applications
-
Implementing networking protocols
-
Implement socket programming
-
Creating web services
Package Used in Networking
J2SE API 的 java.net 包含一组类和接口,用于提供低级通信细节,让您可以编写专注于解决当前问题的程序。
java.net 包提供对两种常见网络协议的支持 −
本章对以下两个主题进行了很好的阐述 −
-
Socket Programming − 这是网络中最广泛使用的概念,它已被非常详细地解释。
-
URL Processing - 这将单独进行介绍。单击此处以了解 Java 语言中的 URL Processing。
Socket Programming in Java Networking
套接字使用 TCP 在两台计算机之间提供通信机制。客户端程序在其通信端创建套接字,并尝试将该套接字连接到服务器。
建立连接时,服务器在其通信端创建一个套接字对象。现在,客户端和服务器可以通过向套接字写入和从套接字读取来进行通信。
java.net.Socket class 表示一个套接字,而 java.net.ServerSocket 类为服务器程序提供了一种侦听客户端并与客户端建立连接的机制。
使用套接字在两台计算机之间建立 TCP 连接时,会发生以下步骤 −
-
服务器实例化一个 ServerSocket 对象,表示通信将在哪个端口号上进行。
-
服务器调用 ServerSocket 类的 accept() 方法。此方法会一直等到客户端通过给定端口连接到服务器。
-
在服务器正在等待后,客户端实例化一个 Socket 对象,指定服务器名称和要连接的端口号。
-
Socket 类的构造函数尝试将客户端连接到指定的服务器和端口号。如果建立了通信,客户端现在就拥有了一个能够与服务器通信的 Socket 对象。
-
在服务器端,accept() 方法返回一个对服务器上与客户端套接字连接的新套接字的引用。
建立连接后,可以使用 I/O 流进行通信。每个套接字都有一个 OutputStream 和一个 InputStream。客户端的 OutputStream 连接到服务器的 InputStream,客户端的 InputStream 连接到服务器的 OutputStream。
TCP 是一个双向通信协议,因此可以同时通过两个流发送数据。以下是提供实现套接字的完整方法集的有用类。
ServerSocket Class Constructors
服务器应用程序使用 java.net.ServerSocket 类获取端口并侦听客户端请求。
ServerSocket 类有四个构造函数 −
Sr.No. |
Method & Description |
1 |
public ServerSocket(int port) throws IOException 尝试创建绑定到指定端口的服务器套接字。如果端口已被其他应用程序绑定,则会发生异常。 |
2 |
public ServerSocket(int port, int backlog) throws IOException 与前面的构造函数类似,backlog 参数指定在等待队列中存储多少个传入客户端。 |
3 |
public ServerSocket(int port, int backlog, InetAddress address) throws IOException 与前面的构造函数类似,InetAddress 参数指定要绑定的本地 IP 地址。InetAddress 用于可能具有多个 IP 地址的服务器,它允许服务器指定接受客户端请求的 IP 地址。 |
4 |
public ServerSocket() throws IOException 创建未绑定的服务器套接字。使用此构造函数时,当您准备绑定服务器套接字时,使用 bind() 方法。 |
如果 ServerSocket 构造函数未引发异常,则表示应用程序已成功绑定到指定端口并已准备好接受客户端请求。
ServerSocket Class Methods
以下是 ServerSocket 类的部分常用方法:
Sr.No. |
Method & Description |
1 |
public int getLocalPort() 返回服务器套接字正在侦听的端口。如果您在构造函数中将 0 传递为端口号,并让服务器为您查找端口,则此方法很有用。 |
2 |
public Socket accept() throws IOException 等待传入客户端。此方法阻塞,直到客户端连接到指定端口上的服务器,或者套接字超时(假设已使用 setSoTimeout() 方法设置超时值)。否则,此方法会无限期阻塞。 |
3 |
public void setSoTimeout(int timeout) 设置服务器套接字在 accept() 期间等待客户端的时间超时值。 |
4 |
public void bind(SocketAddress host, int backlog) 将套接字绑定到 SocketAddress 对象中指定的服务器和端口。如果您已使用无参数构造函数实例化 ServerSocket,请使用此方法。 |
当 ServerSocket 调用 accept() 时,该方法在客户端连接之前不会返回。在客户端连接后,ServerSocket会在未指定端口上创建新的 Socket,并返回对该新 Socket 的引用。在客户端和服务器间建立 TCP 连接后,便可开始通信。
Socket Class Constructors
java.net.Socket 类表示客户端和服务器用于彼此通信的套接字。客户端通过实例化来获取 Socket 对象,而服务器则通过 accept() 方法的返回值来获取 Socket 对象。
Socket 类有五个构造函数供客户端用于连接到服务器 -
Sr.No. |
Method & Description |
1 |
public Socket(String host, int port) throws UnknownHostException, IOException. 此方法尝试连接到指定端口上的指定服务器。如果此构造函数不抛出异常,则连接成功,并且客户端将连接到服务器。 |
2 |
public Socket(InetAddress host, int port) throws IOException 此方法与前面的构造函数相同,只不过主机由 InetAddress 对象表示。 |
3 |
public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException. 连接到指定的主机和端口,在指定地址和端口上的本地主机上创建一个套接字。 |
4 |
public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. 此方法与前面的构造函数相同,只不过主机由 InetAddress 对象表示,而不是 String。 |
5 |
public Socket() 创建一个未连接的套接字。使用 connect() 方法将此套接字连接到服务器。 |
当 Socket 构造器返回时,它不仅仅实例化一个 Socket 对象,而且实际上尝试连接到指定的服务器和端口。
Socket Class Methods
此处列出 Socket 类中的一些感兴趣的方法。请注意,客户端和服务器都有一个 Socket 对象,因此客户端和服务器都可以调用这些方法。
Sr.No. |
Method & Description |
1 |
public void connect(SocketAddress host, int timeout) throws IOException 此方法将套接字连接到指定的主机。仅当您使用无参数构造函数实例化 Socket 时才需要此方法。 |
2 |
public InetAddress getInetAddress() 此方法返回此套接字连接到的其他计算机的地址。 |
3 |
public int getPort() 返回套接字在远程计算机上绑定的端口。 |
4 |
public int getLocalPort() 返回套接字在本地计算机上绑定的端口。 |
5 |
public SocketAddress getRemoteSocketAddress() 返回远程套接字的地址。 |
6 |
public InputStream getInputStream() throws IOException 返回套接字的输入流。输入流连接到远程套接字的输出流。 |
7 |
public OutputStream getOutputStream() throws IOException 返回套接字的输出流。输出流连接到远程套接字的输入流。 |
8 |
public void close() throws IOException 关闭套接字,这使得此套接字对象不再能够再次连接到任何服务器。 |
InetAddress Class Methods
此类表示互联网协议 (IP) 地址。在进行套接字编程时,您可能需要使用以下有用方法:
Sr.No. |
Method & Description |
1 |
static InetAddress getByAddress(byte[] addr) 返回给定原始 IP 地址的 InetAddress 对象。 |
2 |
static InetAddress getByAddress(String host, byte[] addr) 根据提供的 host name 和 IP 地址创建 InetAddress。 |
3 |
static InetAddress getByName(String host) 确定主机 IP 地址,给定主机的名称。 |
4 |
String getHostAddress() 以文本形式返回 IP 地址字符串。 |
5 |
String getHostName() 获取此 IP 地址的主机名。 |
6 |
static InetAddress InetAddress getLocalHost() 返回本地主机。 |
7 |
String toString() 将此 IP 地址转换成字符串。 |
Example of Java Networking
Implementing Socket Client in Java
以下 GreetingClient 是一个客户端程序,它使用套接字连接到服务器并发送问候语,然后等待响应。
// File Name GreetingClient.java
import java.net.*;
import java.io.*;
public class GreetingClient {
public static void main(String [] args) {
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Implementing Socket Server in Java
以下 GreetingServer 程序是一个服务器应用程序示例,它使用 Socket 类监听命令行参数指定的端口号上的客户端—
// File Name GreetingServer.java
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread {
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run() {
while(true) {
try {
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress()
+ "\nGoodbye!");
server.close();
} catch (SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
public static void main(String [] args) {
int port = Integer.parseInt(args[0]);
try {
Thread t = new GreetingServer(port);
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
编译客户端和服务器,然后按以下方式启动服务器—
$ java GreetingServer 6066
Waiting for client on port 6066...
按照以下步骤检查客户端程序 −
Output
$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!