读写套接字

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

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

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

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

让我们遍历该程序并研究有趣的部分。 EchoClient示例中的try-with-resources语句中的以下语句很关键。这些行在 Client 端和服务器之间构建套接字连接,并在套接字上打开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构造函数需要计算机的名称和您要连接的端口号。该示例程序使用第一个command-line argument作为计算机名(主机名),第二个命令行参数作为端口号。在计算机上运行该程序时,请确保所使用的主机名是要连接的计算机的标准 IP 名称。例如,如果您的回显服务器正在计算机echoserver.example.com上运行并且正在侦听端口号 7,如果您想将EchoServer示例用作回显服务器,请首先从计算机echoserver.example.com运行以下命令:

java EchoServer 7

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

java EchoClient echoserver.example.com 7

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

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

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

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

while循环中的最后一条语句从连接到套接字的BufferedReader读取一行信息。 readLine方法 await,直到服务器将信息回显到EchoClient为止。 readline返回时,EchoClient将信息打印到标准输出。

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

该 Client 端程序简单明了,因为回显服务器实现了简单的协议。Client 端将文本发送到服务器,然后服务器将其回显。当您的 Client 端程序与更复杂的服务器(例如 HTTP 服务器)进行通信时,您的 Client 端程序也将更加复杂。但是,基本知识与该程序基本相同:

  • 打开 socket。

  • 打开 Importing 流并将输出流输出到套接字。

  • 根据服务器协议从流中读取和写入流。

  • 关闭流。

  • 关闭 socket。

Client 端与 Client 端之间仅第 3 步有所不同,具体取决于服务器。其他步骤大致相同。