二.六.二.三 测试运行
可以开多个客户端的控制台。 但 idea 默认是不能同时开启同一个程序的控制台的,需要进行设置。
老蝴蝶的 类 public 名称 是 SocketDemo
先运行服务器,再运行 客户端的 main()方法, 打开一个控制台, 再运行 客户端的 main()方法,打开新的控制台
对于第一个控制台
对于第二个控制台
两个客户端都关闭了, 此时服务器仍然是 true, 死循环,接收客户端连接的状态
连接一个客户端,就打印输出一下。
但是,发现有一个问题, 当客户端1 不关闭时,客户端2就无法响应。
客户端1
客户端2
需要用多线程去解决。
二.六.三 多线程 echo
二.六.三.一 关闭工具类
public class CloseUtils { public static void close(Closeable...closeables){ for(Closeable closeable:closeables){ if(null!=closeable){ try { closeable.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
二.六.三.二 客户端
public class Client { //发送者多线程 static class Send implements Runnable{ private Socket client; private DataOutputStream dataOutputStream; private BufferedReader bufferedReader; //是否继续运行的标识 private boolean isRunning; public Send(Socket client){ this.client=client; this.isRunning=true; try { this.dataOutputStream=new DataOutputStream(client.getOutputStream()); this.bufferedReader=new BufferedReader(new InputStreamReader(System.in)); } catch (IOException e) { e.printStackTrace(); isRunning=false; CloseUtils.close(client); } } @Override public void run() { while(this.isRunning){ try { //接收数据 String content=bufferedReader.readLine(); //发送数据 sendMsg(content); if("bye".equalsIgnoreCase(content)||"quit".equalsIgnoreCase(content)){ //修改标识 stop(); CloseUtils.close(dataOutputStream); } } catch (IOException e) { e.printStackTrace(); } } } public void stop(){ this.isRunning=false; } //发送数据 public void sendMsg(String msg){ try { dataOutputStream.writeUTF(msg); } catch (IOException e) { e.printStackTrace(); } } } //接收者 static class Receiver implements Runnable{ private Socket client; private DataInputStream dataInputStream; private boolean isRunning; public Receiver(Socket client){ this.client=client; this.isRunning=true; try { this.dataInputStream=new DataInputStream(client.getInputStream()); } catch (IOException e) { e.printStackTrace(); this.isRunning=false; CloseUtils.close(client); } } @Override public void run() { while(this.isRunning){ String content=readMsg(); System.out.println(content); if("echo:欢迎下次再来".equalsIgnoreCase(content)){ stop(); } } try { CloseUtils.close(this.dataInputStream,client.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } public void stop(){ this.isRunning=false; } //接收数据 public String readMsg(){ String content=""; try { content= dataInputStream.readUTF(); } catch (IOException e) { e.printStackTrace(); } return content; } } public static void main(String[] args) { try { Socket socket=new Socket("localhost",9999); System.out.println("***************连接客户端**************"); //客户端多线程运行发送和接收 new Thread(new Send(socket)).start(); new Thread(new Receiver(socket)).start(); } catch (IOException e) { e.printStackTrace(); } } }
二.六.三.三 服务器端
public class Server { //客户连接类 static class Channel implements Runnable{ private Socket client; private DataInputStream dataInputStream; private DataOutputStream dataOutputStream; private volatile boolean isRunning; public Channel(Socket client){ this.client=client; //标识位 this.isRunning=true; try { this.dataInputStream=new DataInputStream(client.getInputStream()); this.dataOutputStream=new DataOutputStream(client.getOutputStream()); } catch (IOException e) { e.printStackTrace(); CloseUtils.close(dataInputStream,dataOutputStream); } } @Override public void run() { while(this.isRunning){ String content=readMsg(); String responseData=""; if("bye".equalsIgnoreCase(content)||"quit".equalsIgnoreCase(content)){ responseData="echo:欢迎下次再来"; this.isRunning=false; }else{ responseData= "echo:"+content; } sendMsg(responseData); } } //服务器往客户端发送数据 public void sendMsg(String msg){ try { dataOutputStream.writeUTF(msg); } catch (IOException e) { // e.printStackTrace(); CloseUtils.close(dataInputStream,dataOutputStream); } } //服务器读取客户端数据 public String readMsg(){ String content=""; try { content= dataInputStream.readUTF(); } catch (IOException e) { CloseUtils.close(dataInputStream,dataOutputStream); //e.printStackTrace(); } return content; } } public static void main(String[] args) { try { ServerSocket serverSocket=new ServerSocket(9999); System.out.println("********服务器开启************"); while(true){ Socket client=serverSocket.accept();//多线程运行 System.out.println("连接一个客户端"); new Thread(new Channel(client)).start(); } } catch (IOException e) { e.printStackTrace(); } } }
二.六.三.四 测试运行
先运行服务器端,再运行创建客户端1,再运行创建客户端2
客户端1:
现在客户端1 还没有断开链接
看一下客户端2, 发送数据
是可以进行传递数据的。
要理解 多线程 echo 的应用,聊天室时会用得到。
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!