1.关闭流的工具类:
package com.chat.demo01; import java.io.Closeable; import java.io.IOException; /** * 关闭流的工具 * @author snail * */ public class CloseUtil { public static void closeAll(Closeable... io) { for(Closeable temp : io) { try { temp.close(); } catch (IOException e) { // TODO Auto-generated catch block //e.printStackTrace(); } } } }
2.客户端 Client 为了接收来自服务器多个客户端发送的消息 开辟2个线程 (一个接收线程 一个发送线程)
<1>客户端发送数据的线程
package com.chat.demo01;
import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; /** * 发送数据线程 * @author snail * */ public class SendData implements Runnable{ //控制台输入流 private BufferedReader console; private String name; //管道流 private DataOutputStream dos; private boolean isRuning = true; public SendData() { console = new BufferedReader(new InputStreamReader(System.in)); } public SendData(Socket client, String name2) { this(); try { dos = new DataOutputStream(client.getOutputStream()); this.name = name; send(this.name); } catch (IOException e) { //e.printStackTrace(); isRuning = false; CloseUtil.closeAll(dos, console); } } /** * 从控制台获取到数据 * @return */ private String getMsgfromConsole() { try { return console.readLine(); } catch (IOException e) { // TODO Auto-generated catch block //e.printStackTrace(); } return ""; } /** * 发送数据 */ public void send(String str) { String msg = str; if(null != msg && !msg.equals("")) { try { dos.writeUTF(msg); dos.flush(); } catch (IOException e) { //e.printStackTrace(); } } } @Override public void run() { while(isRuning) { //线程体 send(getMsgfromConsole()); } } }
<2>客户端接收数据的线程
package com.chat.demo01; /** * 接收数据线程 * @author snail * */ import java.io.DataInputStream; import java.io.IOException; import java.net.Socket; public class ReceiveData implements Runnable{ //输入流 private DataInputStream dis; private boolean isruning = true; public ReceiveData(Socket client) { try { dis = new DataInputStream(client.getInputStream()); } catch (IOException e) { // TODO Auto-generated catch block //e.printStackTrace(); isruning = false; // CloseUtil.closeAll(dis); } } public String receive() { try { return dis.readUTF(); } catch (IOException e) { // TODO Auto-generated catch block //e.printStackTrace(); isruning = false; //CloseUtil.closeAll(dis); } return "没有发送数据"; } @Override public void run() { while(isruning) { System.out.println(receive()); } } }
客户端 Client:
package com.chat.demo01; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; /** * 创建客户端。发送数据+接收数据 * 写出数据:输出流 * 读取数据:输入流 * @author snail * */ public class Client { public static void main(String[] args) throws UnknownHostException, IOException { System.out.println("请输入名称:"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String name = br.readLine(); Socket client = new Socket("localhost", 9999); //开辟了2个线程 发送和接收数据 new Thread(new SendData(client, name)).start(); new Thread(new ReceiveData(client)).start(); } }
4.服务器 Server:
package com.chat.demo01; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import javax.print.attribute.standard.MediaSize.Other; import javax.xml.crypto.Data; /** * 创建服务器 : 中转站 * @author snail * */ public class Server { //客户端渠道容器 private ArrayList<MyChannel> all =new ArrayList<MyChannel>(); public void start() throws IOException { ServerSocket server = new ServerSocket(9999); //不停接收客户端的socket的 while(true) { Socket client = server.accept(); MyChannel mychanel = new MyChannel(client); //接收多个客户端的管道 all.add(mychanel); //当前的客户端玩家 new Thread(mychanel).start(); } } public static void main(String[] args) throws IOException { // TODO Auto-generated method stub Server server = new Server(); server.start(); } /** * 一条管道 同一个客户端 * @author snail * */ private class MyChannel implements Runnable{ private DataInputStream dis; private DataOutputStream dos; private boolean isruning = true; private String name; public MyChannel(Socket client) { // TODO Auto-generated constructor stub try { dis = new DataInputStream(client.getInputStream()); dos = new DataOutputStream(client.getOutputStream()); this.name = dis.readUTF(); this.send("欢迎进入聊天室"); sendOthers(this.name+"进入聊天室"); } catch (IOException e) { isruning = false; CloseUtil.closeAll(dis, dos); } } /** * 接受的数据 * @return */ public String receive() { try { return dis.readUTF(); } catch (IOException e) { // TODO Auto-generated catch block //e.printStackTrace(); isruning = false; CloseUtil.closeAll( dis); all.remove(this); } return ""; } /** * 发送多个客户端 */ private void sendOthers(String msg1) { String msg =msg1; //你的内容 for(MyChannel other: all) { if(other == this) continue; //发送给其他人 other.send(msg); } } /** * 发送的数据 * @param msg */ public void send(String msg) { if(null == msg && msg.equals("")) return; try { dos.writeUTF(msg); } catch (IOException e) { // TODO Auto-generated catch block //e.printStackTrace(); isruning = false; CloseUtil.closeAll(dos); } } @Override public void run() { // TODO Auto-generated method stub while(isruning) { sendOthers(receive()); } } } }