文档

Java™ 教程-Java Tutorials 中文版
读取和写入套接字
Trail: Custom Networking
Lesson: All About Sockets

读取和写入套接字

让我们看一个简单的例子,它说明程序如何使用 Socket 类建立与服务器程序的连接,然后说明客户端如何通过套接字向服务器发送数据和从服务器接收数据。

示例程序实现连接到 echo 服务器的客户端 EchoClient。echo 服务器从其客户端接收数据并将其回送。示例 EchoServer 实现了一个 echo 服务器。(或者,客户端可以连接到支持 Echo Protocol 的任何主机。)

EchoClient 示例创建一个套接字,从而获得与 echo 服务器的连接。它在标准输入流上读取用户的输入,然后通过将文本写入套接字将该文本转发到 echo 服务器。服务器通过套接字将输入回送给客户端。客户端程序读取并显示从服务器传回给它的数据。

请注意,EchoClient 示例写入和读取其套接字,从而向 echo 服务器发送数据和从 echo 服务器接收数据。

让我们来看看程序并研究有趣的部分。EchoClient 示例中的 try-with-resources 语句中的以下语句至关重要。这些行在客户端和服务器之间建立套接字连接,并在套接字上打开 PrintWriterBufferedReader

String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);

try (
    Socket echoSocket = new Socket(hostName, portNumber);
    PrintWriter out =
        new PrintWriter(echoSocket.getOutputStream(), true);
    BufferedReader in =
        new BufferedReader(
            new InputStreamReader(echoSocket.getInputStream()));
    BufferedReader stdIn =
        new BufferedReader(
            new InputStreamReader(System.in))
)

try-with resources 语句中的第一个语句创建一个新的 Socket 对象,并将其命名为 echoSocket。此处使用的 Socket 构造函数需要计算机的名称和要连接的端口号。示例程序使用第一个 命令行参数 作为计算机的名称(主机名),使用第二个命令行参数作为端口号。在计算机上运行此程序时,请确保你使用的主机名是要连接的计算机的完全限定 IP 名称。例如,如果你的 echo 服务器正在计算机上运行 echoserver.example.com 并且它正在侦听端口号 7,如果要将 EchoServer 示例用作 echo 服务器,请首先从 echoserver.example.com 计算机运行以下命令:

java EchoServer 7

然后,使用以下命令运行 EchoClient 示例:

java EchoClient echoserver.example.com 7

try-with resources 语句中的第二个语句获取套接字的输出流并在其上打开 PrintWriter。类似地,第三个语句获取套接字的输入流并在其上打开 BufferedReader。该示例使用读取器和写入器,以便它可以在套接字上写入 Unicode 字符。

要通过套接字将数据发送到服务器,EchoClient 示例需要写入 PrintWriter。要获得服务器的响应,EchoClientBufferedReader 对象 stdIn 中读取,该对象是在 try-with resources 中的第四个语句创建的。如果你还不熟悉 Java 平台的 I/O 类,则可能希望阅读 Basic I/O

该程序的下一个有趣部分是 while 循环。循环从标准输入流一次读取一行,并通过将其写入连接到套接字的 PrintWriter 立即将其发送到服务器:

String userInput;
while ((userInput = stdIn.readLine()) != null) {
    out.println(userInput);
    System.out.println("echo: " + in.readLine());
}

while 循环中的最后一个语句从连接到套接字的 BufferedReader 中读取一行信息。readLine 方法等待,直到服务器将信息回送回 EchoClient。当 readline 返回时,EchoClient 将信息输出到标准输出。

while 循环继续,直到用户键入输入结束字符。也就是说,EchoClient 示例从用户读取输入,将其发送到 Echo 服务器,从服务器获取响应并显示它,直到它到达输入结束。(你可以通过按 Ctrl-C 键入输入结束字符。)while 循环然后终止,Java 运行时自动关闭连接到套接字的读取器和写入器和标准输入流,并且关闭到服务器的套接字连接。Java 运行时会自动关闭这些资源,因为它们是在 try-with-resources 语句中创建的。Java 运行时以与创建它们相反的顺序关闭这些资源。(这很好,因为连接到套接字的流应该在套接字本身关闭之前关闭。)

此客户端程序简单明了,因为 echo 服务器实现了一个简单的协议。客户端将文本发送到服务器,服务器将其回送回来。当你的客户端程序与更复杂的服务器(如 HTTP 服务器)通信时,你的客户端程序也会更复杂。但是,基本原理与本程序中的基本原理基本相同:

  1. 打开一个套接字。
  2. 打开一个输入流和一个输出流到套接字。
  3. 根据服务器协议读取和写入流。
  4. 关闭流。
  5. 关闭套接字。

只有步骤 3 因客户端而异,具体取决于服务器。其他步骤基本保持不变。


Previous page: What Is a Socket?
Next page: Writing the Server Side of a Socket