package com.rlovep.server; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.HashMap; import java.util.Map; public class TalkServer { //保存聊天线程: private Map<String, ServerThread> map = new HashMap<String, ServerThread>(); public static void main(String[] args) { //启动服务器 new TalkServer().start(); } /** * * @Title: start * @Description: 为每一个客户端创建一个独立线程 * @return:void * @throws * @author peace w_peace@163.com */ public void start(){ //服务器servesocket ServerSocket serverSocket=null; //服务器socket Socket socket=null; try { //服务器创建 serverSocket=new ServerSocket(8888); //死循环,用于接收更多的客户端 while(true){ //聊天线程创建 socket=serverSocket.accept(); //为每一个客户端建立一个服务线程。 ServerThread st=new ServerThread(socket); new Thread(st).start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ //释放资源 try { if(serverSocket!=null){ serverSocket.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * * @ClassName: ServerThread * @Description: 聊天线程 * @author peace w_peace@163.com * @date 15 Oct 2015 8:31:44 pm * */ private class ServerThread implements Runnable{ //相应的socket private Socket socket=null; private BufferedReader in=null; private PrintWriter out=null; //每个聊天的名字 private String name=null; //聊天头 private String meshead=null; //停止线程标志位 private boolean flag=true; //单聊标志位: private boolean sin=false; /** * * <p>Title:线程构造器 </p> * <p>Description:用来创建线程,以及初始化,和将线程加入map </p> * @param socket * @throws IOException */ public ServerThread(Socket socket) throws IOException { //获得socket this.socket=socket; //获得输出和输入 out=new PrintWriter(socket.getOutputStream(),true); //获得用户名字 in=new BufferedReader(new InputStreamReader(socket.getInputStream())); name=in.readLine(); System.out.println(name+"上线了"); //制作聊天头 meshead=name+"["+socket.getInetAddress().getHostAddress()+":"+socket.getPort()+"]"; //将线程加入map:key为名字;value为线程 map.put(name, this); //提醒所有用户 send(meshead+"上线了"); } /** * * @Title: send * @Description: 发送消息(群发) * @param msg * @return:void * @throws * @author peace w_peace@163.com */ public void send(String msg){ //迭代群发 for(ServerThread thread:map.values()){ thread.out.println(msg); } } /** * * @Title: Receiver * @Description: 接收消息,并转发 * @throws IOException * @return:void * @author peace w_peace@163.com */ public void Receiver() throws IOException{ String str=null; ServerThread qq=null; //接收消息 while((str=in.readLine())!=null){ //如果消息为quit则退出 if("quit".equalsIgnoreCase(str)){ stop(); //给客户端发送关闭链接命令 out.println("disconnect"); break; } //判断是否为单聊 if(sin==false) { if(str.equals("single")){ //如果为单聊就获得想要跟谁聊 if((str=in.readLine())!=null){ //获得另外一个客户端线程 qq=map.get(str); if(qq!=null) sin=true; } } else { //转发消息 群发 send(meshead+str); } } //如果是单聊就给对应的客户端发送消息; else{ //如果为q则退出单聊 if(str.equals("q")){ sin=false; qq.out.println(name+"对话结束"); } //否则发送消息 else qq.out.println(name+"对你说:"+str); } } } /** * * @Title: stop * @Description: 停止函数 * @return:void * @throws * @author peace w_peace@163.com */ public void stop(){ flag=false; //下线移去码map; map.remove(name); send(meshead+"已经下线了"); } /** * run方法 */ @Override public void run() { try { while(flag){ //不停接收消息 Receiver(); } } catch(SocketException e){ stop();//客户端直接关闭引发的错误; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ //释放资源 try { if(socket!=null){ socket.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }