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

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

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

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

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

  • 服务器调用 ServerSocket 类的 accept() 方法。此方法等待客户端连接到给定端口上的服务器。

  • 服务器等待后,客户端实例化一个 Socket 对象,并指定服务器名称和端口号

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

  • 在服务器端,accept() 方法返回对新套接字的引用在连接到客户端套接字的服务器上。

建立连接后,可以使用 I/O 流进行通信。每个套接字都有一个输出流和一个输入流。客户端的OutputStream连接到服务器的InputStream,客户端的InputStream连接到服务器的OutputStream。 TCP 是双向通信协议,因此数据可以同时通过两个流发送。

Java Sockets 的优点

  • 平台独立性 - Java Sockets 的最大优点之一是它们是平台独立的。这意味着相同的 Java 代码可以在多个操作系统和设备上运行,而无需修改。这样可以轻松地跨不同系统部署基于网络的应用程序,并确保应用程序可以在不同设备上运行,而无需特定于平台的代码。

  • 易于使用 - Java Sockets 也相对易于使用,即使对于网络编程新手来说也是如此。 Java API 提供了一个简单、一致的接口来创建和管理套接字,这使得无需了解底层网络协议即可轻松实现基于网络的应用程序。

  • 可扩展性 - Java Sockets 具有高度可扩展性,使其适合大规模基于网络的应用程序。它们可以轻松处理数千个同时连接,并可用于创建可以处理高流量的分布式系统。

  • 安全性 - Java Sockets 提供对安全通信的内置支持,包括 SSL 和 TLS 加密。这使得创建安全的基于网络的应用程序变得容易,并确保敏感数据在传输过程中受到保护。

  • 多线程 - Java Sockets 支持多线程,这意味着可以使用多个线程同时处理多个连接。这提高了基于网络的应用程序的性能,并允许它们处理大量请求而不会过载。

Java Sockets 的缺点

  • 复杂性 - 虽然 Java Sockets 相对容易使用,但实现起来仍然很复杂,特别是对于刚接触网络编程的开发人员来说。这种复杂性使得基于网络的应用程序的调试和故障排除变得困难,这可能非常耗时且令人沮丧。

  • 延迟 - Java Sockets 可以在基于网络的应用程序中引入延迟,特别是在处理大量数据时。对于需要实时通信的应用程序(例如在线游戏或视频会议)来说,这可能是一个问题。

  • 资源密集型 - Java 套接字可以是资源密集型,特别是在处理大量连接或大量数据时。对于资源有限的系统(例如移动设备或嵌入式系统)来说,这可能是一个问题。

  • 协议支持有限 - Java Sockets 支持数量有限网络协议,这可能是某些类型的基于网络的应用程序的限制。这可能会使创建需要使用专有协议与其他系统通信的应用程序变得困难。

  • 潜在的安全漏洞 - Java 套接字,与任何其他系统一样基于网络的应用程序很容易受到安全威胁,例如黑客攻击和中间人攻击。在设计和实现基于 Java Socket 的系统时必须特别注意安全性,以确保敏感数据受到保护,并识别和解决潜在的漏洞。

Java Socket 示例应用程序

  • 聊天应用程序 - Java Sockets 通常用于创建聊天应用程序,例如即时消息程序和在线聊天室。这些类型的应用程序通常使用客户端-服务器架构,其中客户端连接到中央服务器以发送和接收消息。

  • 文件传输应用程序 - Java Sockets 还可用于创建文件传输应用程序,例如点对点文件共享程序。这些类型的应用程序使用点对点架构,其中每个设备既充当客户端又充当服务器。这允许设备之间直接通信,从而提高文件传输的速度和可靠性。

  • 远程控制应用程序 - 也可以使用 Java 套接字创建远程控制应用程序,例如远程桌面软件。这些类型的应用程序使用客户端-服务器架构,其中客户端连接到远程服务器以控制服务器的桌面。这允许用户从任何具有互联网连接的设备访问和控制他们的桌面。

  • 多人游戏 - Java Sockets 也常用于创建多人游戏游戏,例如在线角色扮演游戏和第一人称射击游戏。这些类型的应用程序通常使用客户端-服务器架构,其中客户端连接到中央服务器来玩游戏。服务器充当客户端之间的中介,处理通信和游戏逻辑。

  • 物联网应用 - Java Sockets 也可用于物联网(Internet of IoT)物)应用,例如智能家居系统。这些类型的应用程序使用客户端-服务器架构,其中物联网设备连接到中央服务器以发送和接收数据。这允许对设备进行远程监视和控制,以及数据收集和分析。

Socket 客户端示例

以下 GreetingClient 是一个客户端使用套接字连接到服务器并发送问候语,然后等待响应的程序。

示例

// 文件名 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();
      }
   }
} 

套接字服务器示例

以下GreetingServer 程序是一个服务器应用程序的示例,它使用 Socket 类在由命令行参数指定的端口号上侦听客户端 -

示例

// 文件名 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... 

检查客户端程序如下 

输出

$ 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!