服务器:
package com.thread.socket.demo; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; /** * 服务器 * 创建多线程服务器 * @author Qixuan.Chen * 创建时间:2015年7月3日 */ public class MultiServer { private List<ChannelManager> all = new ArrayList<ChannelManager>(); public static void main(String[] args) throws IOException { new MultiServer().start(); } public void start() throws IOException { ServerSocket server = new ServerSocket(9999); while(true) { Socket client = server.accept(); ChannelManager channel = new ChannelManager(client); all.add(channel);//统一管理 new Thread(channel).start();//一条道路 } } /** * 一个内部类, * 一个客户端,一条道路 * 1、输入流 * 2、输出流 * 3、接收数据 * 4、发送数据 */ class ChannelManager implements Runnable{ private DataInputStream dis; private DataOutputStream dos; private boolean isRunning = true; private String name; public void run(){ while(isRunning) { sendOthers(receive(),false); } } //无参数构造函数 public ChannelManager(){ } //初始化 public ChannelManager(Socket client){ try { dis = new DataInputStream(client.getInputStream()); dos = new DataOutputStream(client.getOutputStream()); this.name = dis.readUTF(); //System.out.println(this.name); this.send("欢迎进入聊天室"); sendOthers(this.name+"进入了聊天室",true); } catch (IOException e) { CloseUtil.closeAll(dos,dis); isRunning = false; } } //接收数据 private String receive() { String msg = ""; try { msg = dis.readUTF(); } catch (IOException e) { CloseUtil.closeAll(dis); isRunning = false; all.remove(this);//移除自身 } return msg; } //发送数据 private void send(String msg) { if(null==msg||msg.equals("")) { return; } try { dos.writeUTF(msg); dos.flush(); } catch (IOException e) { CloseUtil.closeAll(dos); isRunning = false; all.remove(this);//移除自身 } } //发送给其他客户端 private void sendOthers(String msg,boolean sys) { //是否为私聊 约定 if(msg.startsWith("@")&& msg.indexOf(":")>-1) { //获取name String name = msg.substring(1,msg.indexOf(":")); String contant = msg.substring(msg.indexOf(":")+1); for(ChannelManager other:all) { if(other.name.equals(name)) { other.send(this.name+"对你悄悄的说:"+contant); } } } else { for(ChannelManager other:all) { if(other ==this) { continue; } if(sys==true)//系统信息 { other.send("系统信息:"+msg); } else { //发送其它客户端 other.send(this.name+"对所有人说"+msg); } } } /* //遍历容器 for(MyChannel others:all) { if(others == this) { continue; } //发送给其他客户端 others.send(msg); }*/ } }//内部类:END }发送数据处理类:
package com.thread.socket.demo; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; /** * 发送数据线程,用于发送数据 * 发送信息(供客服端使用) * @author Qixuan.Chen * 创建时间:2015年7月17日 */ public class Send implements Runnable{ //控制台输入流 private BufferedReader console; //管道输出流 private DataOutputStream dos; //控制线程标识 private boolean isRunning = true; //名称 private String name; public void run() { while(isRunning) { send( getMsgFromConsole()); } } //初始化 public Send() { console = new BufferedReader(new InputStreamReader(System.in)); } public Send(Socket client,String name) { this(); try { dos = new DataOutputStream(client.getOutputStream()); this.name = name; send(this.name); } catch (IOException e) { //e.printStackTrace(); System.out.println(e); } } //1、从控制台接收数据 private String getMsgFromConsole() { try { return console.readLine(); } catch (IOException e) { e.printStackTrace(); } return ""; } /** * 1、从控制台接收数据 * 2、发送数据 */ public void send(String msg) { try { if(null!=msg&& !msg.equals("")) { dos.writeUTF(msg); dos.flush();//强制刷新 } } catch (IOException e) { //e.printStackTrace(); isRunning = false; CloseUtil.closeAll(dos,console); } } }
package com.thread.socket.demo; import java.io.DataInputStream; import java.io.IOException; import java.net.Socket; /** * 接收线程:用于接收数据 * 接收信息(供客服端使用) * @author Qixuan.Chen * 创建时间:2015年7月17日 */ public class Receive implements Runnable{ //管道的数据输入流 private DataInputStream dis ; //线程标识 private boolean isRunning = true; public Receive() { } public Receive(Socket client) { try { dis = new DataInputStream(client.getInputStream()); } catch (IOException e) { isRunning = false; CloseUtil.closeAll(dis); System.out.println("close"); } } //接收数据的方法 public String receive() { String msg = ""; try { msg = dis.readUTF(); } catch (IOException e) { isRunning = false; CloseUtil.closeAll(dis); } return msg; } public void run() { //线程体 while(isRunning){ System.out.println(receive()); } } }
package com.thread.socket.demo; import java.io.Closeable; import java.io.IOException; /** * 关闭流的方法 */ public class CloseUtil { public static void closeAll(Closeable ... io) { for(Closeable temp:io) { if(null==temp) { try { temp.close(); } catch (IOException e) { System.out.println(e); e.printStackTrace(); } } } } }
package com.thread.socket.demo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; /** * 客户端 * 创建客户端:发送数据+接收数据 * 写出数据:输出流 * 读取数据:输入流 * 输入流与输出流在同一个线程内 应该独立出来 * 加入名称 */ public class Client { public static void main(String[] args) throws IOException { System.out.println("请输入用户名:"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String name = br.readLine(); if(name.equals("")) { return; } Socket client = new Socket("localhost",9999); new Thread(new Send(client,name)).start();//一条路径 new Thread(new Receive(client)).start();//一条路径 } }