Java 简明教程

Java - Networking

Java Networking

Java networking(或 Java network programming)指的是编写在多设备(计算机)上执行的程序,其中所有设备都使用网络连接在一起。

Advantages of Java Networking

  1. Creating server-client applications

  2. Implementing networking protocols

  3. Implement socket programming

  4. Creating web services

Package Used in Networking

J2SE API 的 java.net 包含一组类和接口,用于提供低级通信细节,让您可以编写专注于解决当前问题的程序。

java.net 包提供对两种常见网络协议的支持 −

  1. TCP - TCP 是传输控制协议的缩写,它允许在两个应用程序之间进行可靠的通信。TCP 通常使用 Internet 协议,称为 TCP/IP。

  2. UDP - UDP 是用户数据报协议的缩写,是一种无连接协议,允许在应用程序之间传输数据包。

本章对以下两个主题进行了很好的阐述 −

  1. Socket Programming − 这是网络中最广泛使用的概念,它已被非常详细地解释。

  2. URL Processing - 这将单独进行介绍。单击此处以了解 Java 语言中的 URL Processing

Socket Programming in Java Networking

套接字使用 TCP 在两台计算机之间提供通信机制。客户端程序在其通信端创建套接字,并尝试将该套接字连接到服务器。

建立连接时,服务器在其通信端创建一个套接字对象。现在,客户端和服务器可以通过向套接字写入和从套接字读取来进行通信。

java.net.Socket class 表示一个套接字,而 java.net.ServerSocket 类为服务器程序提供了一种侦听客户端并与客户端建立连接的机制。

使用套接字在两台计算机之间建立 TCP 连接时,会发生以下步骤 −

  1. 服务器实例化一个 ServerSocket 对象,表示通信将在哪个端口号上进行。

  2. 服务器调用 ServerSocket 类的 accept() 方法。此方法会一直等到客户端通过给定端口连接到服务器。

  3. 在服务器正在等待后,客户端实例化一个 Socket 对象,指定服务器名称和要连接的端口号。

  4. Socket 类的构造函数尝试将客户端连接到指定的服务器和端口号。如果建立了通信,客户端现在就拥有了一个能够与服务器通信的 Socket 对象。

  5. 在服务器端,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!