文档

Java™教程
隐藏目录
从套接字读取和写入
导航: 自定义网络
课程: 关于套接字的一切

从套接字读取和写入数据

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

示例程序实现了一个客户端,EchoClient,它连接到一个回显服务器。回显服务器接收来自客户端的数据并将其回显。示例EchoServer实现了一个回显服务器。(或者,客户端可以连接到支持回显协议的任何主机。)

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

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

让我们逐步浏览程序并研究其中有趣的部分。在EchoClient示例中,try-with-resources语句中的以下语句非常关键。这些行在客户端和服务器之间建立套接字连接,并在套接字上打开一个PrintWriter和一个BufferedReader

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名称。例如,如果您的回显服务器正在计算机echoserver.example.com上运行,并且它正在侦听端口号7,则首先在计算机echoserver.example.com上运行以下命令,如果您想将EchoServer示例用作回显服务器:

java EchoServer 7

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

java EchoClient echoserver.example.com 7

try-with资源语句的第二个语句中,获取套接字的输出流并打开一个名为outPrintWriter。类似地,第三个语句获取套接字的输入流并打开一个名为inBufferedReader。示例使用读写器以便通过套接字传输Unicode字符。如果您对Java平台的I/O类还不熟悉,建议阅读基本I/O

程序的下一个有趣部分是while循环。该循环使用BufferedReader对象stdIn从标准输入流中一次读取一行,该对象在try-with资源语句的第四个语句中创建。然后,循环通过将该行写入与套接字连接的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运行时以它们创建的相反顺序关闭这些资源。(这样做是正确的,因为连接到套接字的流应该在套接字本身关闭之前关闭。)

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

  1. 打开一个socket。
  2. 打开一个输入流和输出流到socket。
  3. 根据服务器的协议从流中读取和写入数据。
  4. 关闭流。
  5. 关闭socket。

只有第三步因服务器而异,其余步骤基本相同。


上一页: 什么是Socket?
下一页: 编写Socket的服务器端