通过前两个小节的讲解,了解了 ServerSocket、Socket 类的基本用法。为了更好的掌握这两个类的使用,接下来通过一个 TCP 通信的案例来进一步学习这两个类的用法。
要实现 TCP 通信需要创建一个服务器端程序和客户端程序,为了保证数据传输的安全性,首先需要实现服务器端程序,如下所示:
import java.io.OutputStream;
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception {
//创建 TCPServer 对象,并调用 listen()方法
new TCPServer().listen();
}
}
//TCPServer 服务端
class TCPServer{
private static final int PORT = 7788; //定义一个端口
//定义一个 listen()方法,抛出异常
public void listen() throws Exception {
//创建 ServerSocket 对象
ServerSocket serverSocket = new ServerSocket(PORT);
//调用 ServerSocket 的 accept()方法接收数据
Socket client = serverSocket.accept();
//获取客户端的输出流
OutputStream os = client.getOutputStream();
System.out.println("开始与客户端交互数据");
//当客户端连接到服务端时,向客户端输出数据
os.write(("我爱你").getBytes());
Thread.sleep(5000); //模拟执行其他功能占用的时间
System.out.println("结束与客户端交互数据");
os.close();
client.close();
}
}
运行结果如下所示:
上述代码块中创建了一个服务器端程序,用于接收客户端发送的数据。在创建 ServerSocket 对象时指定了端口号,并调用该对象的 accept()方法。从运行结果可以看出,控制台中的光标一直在闪动,这是因为 accept()方法发生阻塞,程序暂时停止运行,直到有客户端来访问时才会结束这种阻塞状态。这时该方法会返回一个 Socket 类型的对象用于表示客户端,通过该对象获取与客户端关联的输出流,并向客户端发送消息,同时执行 Thread.sleep(5000)语句模拟服务器执行其他功能占用的时间。最后,调用 Socket 对象的 close()方法将通信关闭。
接下来编写客户端程序,如下所示:
import java.io.InputStream;
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
//创建 TCPClient 对象,调用 connect()方法
new TCPClient().connect();
}
}
//TCP 客户端
class TCPClient{
private static final int PORT = 7788; //定义一个端口
public void connect() throws Exception, Exception {
//创建一个 Socket 并连接到给出地址和端口号的计算机
Socket client = new Socket(InetAddress.getLocalHost(), PORT);
InputStream is = client.getInputStream(); //得到数据的流
//定义一个 1024 个字节数数组的缓冲区
byte[] buf = new byte[1024];
int len = is.read(buf); //将数据读到缓冲区中
System.out.println(new String(buf, 0, len)); //将缓冲区中的数据输出
is.close();
client.close();
}
}
运行结果如下所示:
上述代码块中,创建了一个客户端程序,用于向服务端发送数据。在客户端创建的 Socket 对象与服务器端建立连接后,通过 Socket 对象获得输入流读取服务端发来的数据,并打印出下图所示的结果。同时,服务端程序会结束阻塞状态,并在控制台打印出“开始与客户端交互数据”消息,然后向客户端发出数据“我爱你”,在休眠 5 秒后,打印出“结束与客户端交互数据”,此时本次通信结束。如下图所示。