网络编程【TCP单向通信、TCP双向通信、一对多应用、一对多聊天服务器】(二)-全面详解(学习总结---从入门到深化)(上):https://developer.aliyun.com/article/1419279
创建客户端
/** * 用于发送消息的线程类 */ class ClientSend extends Thread{ private Socket socket; public ClientSend(Socket socket){ this.socket = socket; } @Override public void run() { this.sendMsg(); } /** * 发送消息 */ private void sendMsg(){ //创建Scanner对象 try(Scanner scanner = new Scanner(System.in); //创建向对方输出消息的流对象 PrintWriter pw = new PrintWriter(this.socket.getOutputStream());) { while(true){ String msg = scanner.nextLine(); pw.println(msg); pw.flush(); } }catch(Exception e){ e.printStackTrace(); } } } /** * 用于接收消息的线程类 */ class ClientReceive extends Thread{ private Socket socket; public ClientReceive(Socket socket){ this.socket = socket; } @Override public void run() { this.receiveMsg(); } /** * 用于接收对方消息的方法 */ private void receiveMsg(){ //创建用于接收对方发送消息的流对象 try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));){ while(true){ String msg = br.readLine(); System.out.println("他说:"+msg); } }catch(Exception e){ e.printStackTrace(); } } } public class ChatSocketClient { public static void main(String[] args) { try { Socket socket = new Socket("127.0.0.1", 8888); System.out.println("连接成功!"); new ClientSend(socket).start(); new ClientReceive(socket).start(); }catch(Exception e){ e.printStackTrace(); } } }
优化点对点聊天应用
/** * 发送消息线程 */ class Send extends Thread{ private Socket socket; private Scanner scanner; public Send(Socket socket,Scanner scanner){ this.socket = socket; this.scanner = scanner; } @Override public void run() { this.sendMsg(); } /** * 发送消息 */ private void sendMsg(){ //创建向对方输出消息的流对象 try(PrintWriter pw = new PrintWriter(this.socket.getOutputStream())) { while(true){ String msg = scanner.nextLine(); pw.println(msg); pw.flush(); } }catch(Exception e){ e.printStackTrace(); } } } /** * 接收消息的线程 */ class Receive extends Thread{ private Socket socket; public Receive(Socket socket){ this.socket = socket; } @Override public void run() { this.receiveMsg(); } /** * 用于接收对方消息的方法 */ private void receiveMsg(){ //创建用于接收对方发送消息的流对象 try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()))){ while(true){ String msg = br.readLine(); System.out.println("他说:"+msg); } }catch(Exception e){ e.printStackTrace(); } } } public class GoodTCP { public static void main(String[] args) { Scanner scanner = null; ServerSocket serverSocket = null; Socket socket = null; try{ scanner = new Scanner(System.in); System.out.println("请输入:server,<port> 或者:<ip>,<port>"); String str = scanner.nextLine(); String[] arr = str.split(","); if("server".equals(arr[0])){ //启动服务端 System.out.println("TCP Server Listen at "+arr[1]+" ....."); serverSocket = new ServerSocket(Integer.parseInt(arr[1])); socket = serverSocket.accept(); System.out.println("连接成功!"); }else{ //启动客户端 socket = new Socket(arr[0],Integer.parseInt(arr[1])); System.out.println("连接成功!"); } //启动发送消息的线程 new Send(socket,scanner).start(); //启动接收消息的线程 }catch(Exception e){ e.printStackTrace(); }finally{ if(serverSocket != null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
一对多应用
一对多应用设计
各socket对间独立问答,互相间不需要传递信息。
一对多应答型服务器
/** * 定义消息处理线程类 */ class Msg extends Thread{ private Socket socket; public Msg(Socket socket){ this.socket = socket; } @Override public void run() { this.msg(); } /** * 将从客户端读取到的消息写回给客户端 */ private void msg(){ try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); PrintWriter pw = new PrintWriter(this.socket.getOutputStream())){ while(true){ pw.println(br.readLine()+" [ok]"); pw.flush(); } }catch(Exception e){ e.printStackTrace(); System.out.println(this.socket.getInetAddress()+" 断线了!"); } } } public class EchoServer { public static void main(String[] args) { try(ServerSocket serverSocket = new ServerSocket(8888)){ //等待多客户端连接 while(true){ Socket socket = serverSocket.accept(); new Msg(socket).start(); } }catch(Exception e){ e.printStackTrace(); } } }
一对多聊天服务器
服务器设计
1、服务器的连接设计
2、服务器的线程设计
创建一对多聊天服务应用
/** * 接收客户端消息的线程类 */ class ChatReceive extends Thread{ private Socket socket; public ChatReceive(Socket socket){ this.socket =socket; } @Override public void run() { this.receiveMsg(); } /** * 实现接收客户端发送的消息 */ private void receiveMsg(){ try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()))){ while(true){ String msg = br.readLine(); synchronized ("abc"){ //把读取到的数据写入公共数据区 ChatRoomServer.buf=" ["+this.socket.getInetAddress()+"] "+msg; //唤醒发送消息的线程对象。 "abc".notifyAll(); } } }catch(Exception e){ e.printStackTrace(); } } } /** * 向客户端发送消息的线程类 */ class ChatSend extends Thread{ private Socket socket; public ChatSend(Socket socket){ this.socket = socket; } @Override public void run() { this.sendMsg(); } /** * 将公共数据区的消息发送给客户端 */ private void sendMsg(){ try(PrintWriter pw = new PrintWriter(this.socket.getOutputStream())){ while(true){ synchronized ("abc"){ //让发送消息的线程处于等待状态 "abc".wait(); //将公共数据区中的消息发送给客户端 pw.println(ChatRoomServer.buf); pw.flush(); } } }catch(Exception e){ e.printStackTrace(); } } } public class ChatRoomServer { //定义公共数据区 public static String buf; public static void main(String[] args) { System.out.println("Chat Server Version 1.0"); System.out.println("Listen at 8888....."); try(ServerSocket serverSocket = new ServerSocket(8888)){ while(true){ Socket socket = serverSocket.accept(); System.out.println("连接到:"+socket.getInetAddress()); new ChatReceive(socket).start(); new ChatSend(socket).start(); } }catch(Exception e){ e.printStackTrace(); } } }