最近在读《分布式Java应用基础与实践》,写代码加深一下理解。
基于JavaAPI实现消息方式的系统间通信:TCP/IP+BIO,TCP/IP由Socket实现,BIO即阻塞式的I/O,这个阻塞具体体现在服务端和客户端在接收对方发送的数据和发送数据到对方时所产生的阻塞。
一、服务端代码实现
public static void main(String[] args) {
try {
ServerSocket serverSocket=new ServerSocket(1234);
//serverSocket.setSoTimeout(6000);//设置6秒若没有客户端连接则超时报错:Accept timed out
//serverSocket.setSoTimeout(0);//设置为0则等待客户端连接时间无限大
Socket socket=serverSocket.accept();
socket.setSoTimeout(6000);//连接后,超过6秒没有接收到客户端信息,则超时
PrintWriter pw=new PrintWriter(socket.getOutputStream(),true);
pw.println("Hello,this is server");
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String readClientMeassage=br.readLine();
System.out.println("Client Message:"+readClientMeassage);
} catch (IOException e) {
e.printStackTrace();
}
}
注意ServerSocket与Socket的setSoTimeout意义是不一样的,ServerSocket的setSoTimeout是等待
建立连接超时。Socket的setSoTimeout是等待
接收数据超时。
二、客户端代码实现
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1", 1234);
//socket.setSoTimeout(6000);//设置读取服务端信息超时时间
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pw=new PrintWriter(socket.getOutputStream(),true);
pw.println("Hello,this is Client");//一直阻塞,直到写入操作系统完毕,或网络IO异常
String result=br.readLine();//阻塞读取服务端的返回信息,直到读取完毕或网络IO异常
System.out.println("Server Message:"+result);
} catch (IOException e) {
e.printStackTrace();
}
}
显然阻塞式I/O服务端不支持同时多个连接。解决办法是accept获取Socket后为每一个Socket开启一个线程去处理。因为创建线程越多就会降低系统性能,可以设置有限的线程数来解决:建立线程池,线程池里面建立有限的线程,并且里面的线程可重用,避免重复创建。线程池最大缺点是线程数有限,线程资源竞争,导致客户端等待。