JAVASE聊天室

客户端:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;

import Clinet.untils.InputUtil;
import Configs.Configs;

public class ClientDemo {
private static OutputStream out;
private static InputStream in;
public static Scanner sc;

public static void main(String[] args) {
    try {
        Socket s = new Socket("127.0.0.1", 1008);
        out = s.getOutputStream();
        in = s.getInputStream();
        sc = new Scanner(System.in);

        while (true) {
            System.out.println("请您输入您要注册的用户名:");
            String username = sc.nextLine();
            out.write(username.getBytes());
            byte[] bys = new byte[1024];
            int len = in.read(bys);
            String msg = new String(bys, 0, len);
            if (msg.equals("yes")) {
                System.out.println(username + "登陆成功");
                break;
            } else {
                System.out.println("该用户已存在,请重新输入用户名");
            }

        }

        ClientThread ct = new ClientThread(in);
        ct.start();

        boolean flag  =true ;
        while (flag) {
            System.out.println("请选择类型:1私聊,2公聊,3在线人数,4下线");
            // 消息类型 消息对象:消息内容:消息类型
            int num = InputUtil.inputIntType(new Scanner(System.in));
            switch (num) {
            case 1:
                // 私聊
                privateTalk();
                break;
            case 2:
                // 公聊
                publicTalk();
                break;
            case 3:
                // 在线人数
                System.out.println("当前在线人数....");
                showTalker();
                break;
            case 4:
                // 下线
                downLine();
                flag=false;
                ct.flag=false;
                break;
            }
        }
        s.close();

    } catch (SocketException e) {

    } catch (IOException e) {

        e.printStackTrace();
    }finally {

    }
}

private static void downLine() {
    try {
        String msg = "null" + ":" + "null" + ":" + Configs.MSG_EXIT;
        out.write(msg.getBytes());

    } catch (IOException e) {
        e.printStackTrace();
    }

}

private static void showTalker() throws IOException {
        while (true) {
            String msg = "null"+":"+"null"+":"+Configs.MSG_ONLIST;
            out.write(msg.getBytes());
            break;
        }

}

private static void publicTalk() {
    System.out.println("当前处于公聊模式.....");
    try {
        while (true) {
            String msg = sc.nextLine();
            if (msg.equals("-q")) {
                break;
            }
            msg = "null" + ":" + msg + ":" + Configs.MSG_PUBLIC;
            out.write(msg.getBytes());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

}

private static void privateTalk() {
    try {
        System.out.println("当前处于私聊模式.......");
        while (true) {
            String msg = sc.nextLine();
            if ("-q".equals(msg)) {
                break;
            }
            msg = msg + ":" + Configs.MSG_PRIVATE;
            out.write(msg.getBytes());
        }

    } catch (IOException e) {
        e.printStackTrace();
    }

}

}
客户端读取消息的线程:
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;

import Clinet.untils.TimeUtil;
import Configs.Configs;

public class ClientThread extends Thread {
private InputStream in;
boolean flag=true;
public ClientThread(InputStream in) {br/>this.in=in;
}
@Override
public void run() {
try {
while(flag) {
byte[] bys=new byte[1024];
int len=in.read(bys);
String client=new String(bys, 0, len);
String[] split=client.split(":");
String sender=split[0];
String msg=split[1];
int msgType=Integer.parseInt(split[2]);
long time=Long.parseLong(split[3]);
int num=1;
String data=TimeUtil.changeMils2Date(time, "yyyy-MM-dd HH:mm:ss");

            if(msgType==Configs.MSG_PRIVATE) {
                //私聊
                System.out.println(data);
                System.out.println(sender+"对你说:"+msg);
            }else if(msgType==Configs.MSG_PUBLIC) {
                //公聊
                System.out.println(data);
                System.out.println(sender+"对大家说:"+msg);
            }else if(msgType==Configs.MSG_ONLINE) {
                System.out.println(sender+msg+data);
            }else if(msgType==Configs.MSG_ONLIST) {
                System.out.println(msg);
            }else if(msgType==Configs.MSG_EXIT) {
                System.out.println(sender+msg);
            }

        }
    } catch (SocketException e) {

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}
工具
消息类型模式:
public class Configs {

//私聊
//ctrl+shift+x :小转大
//ctrl+shift+y:大转小
public static final int MSG_PRIVATE = 100 ; 

//公聊
public static final int MSG_PUBLIC = 200 ;

//上线提醒
public static final int MSG_ONLINE = 300 ;

//在线列表
public static final int MSG_ONLIST =400 ;

//退出
public static final int MSG_EXIT = 500 ;

//文件
public static final int MSG_FILE = 600 ;

}
客户端录入信息为整数工具:
import java.util.Scanner;

public class InputUtil {

public static int inputIntType(Scanner sc) {
    int choose = 0;
    while (true) {
        try {
            //录入用户输入的整数
            choose = sc.nextInt();
            break;
        } catch (Exception e) {
            sc = new Scanner(System.in);
            System.out.println("输入的类型不正确,请重新输入:");
        }
    }
    return choose;
}

}
将时间毫秒数转换为制定的日期格式工具类:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TimeUtil {
//2016-10-27 19:20:12 yyyy-MM-dd HH:mm:ss
public static String changeDate2Week(String dateStr,String formatStr){
SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
Date date = null;
try {
date = sdf.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat sdf1 = new SimpleDateFormat("E");
return sdf1.format(date);
}

//把字符串的日期转为毫秒数
public static long changeDate2Mils(String dateStr,String formatStr){
    SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
    Date date = null;
    try {
        date = sdf.parse(dateStr);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return date.getTime();
}

//把毫秒数转为指定的格式的日期
public static String changeMils2Date(long mils,String formatStr){
    SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
    Date date = new Date(mils);
    return sdf.format(date);
}

public static String changeDate2CustomerMsg(String dateStr){
    long mils = changeDate2Mils(dateStr,"yyyy-MM-dd_HH:mm:ss");
    long nowMils = System.currentTimeMillis();
    long offsetMils = nowMils - mils;
    String msg = "";
    if(offsetMils<1000*60*2){
        msg = "刚刚";
    }else if(offsetMils<1000*60*60){
        msg = (offsetMils/(1000*60))+"分钟前";
    }else if(offsetMils<1000*60*60*24){
        msg = (offsetMils/(1000*60*60))+"小时前";
    }else if(offsetMils<1000*60*60*24*2){
        msg = "昨天";
    }else{
        String nowYear = changeMils2Date(nowMils, "yyyy");
        String year = changeMils2Date(mils, "yyyy");
        if(nowYear.equals(year)){
            msg = changeMils2Date(mils, "MM月dd日");
        }else{
            msg = changeMils2Date(mils, "yyyy年MM月dd日");
        }
    }
    return msg;
}

}
服务端--------------------------------------------------------------------------------------------------------------------------------------------------------
服务端import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

import UserCheck.ServerUserCheck;

public class ServerDemo {

public static void main(String[] args) throws IOException   {
    HashMap hm = new HashMap();
    ServerSocket ss=new ServerSocket(1008);

    System.out.println("服务器已开启,正在等待客户端的连接...");
    int i=1;
    while(true) {
        Socket s=ss.accept();
        System.out.println("第"+(i++)+"个客户端已连接...");
        InputStream in=s.getInputStream();
        OutputStream out=s.getOutputStream();;
        ServerUserCheck su=new ServerUserCheck(s,hm);
        su.start();
    }

}

}
服务端保存用户名的线程:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Set;

import Configs.Configs;
import Server.ServerThread;

public class ServerUserCheck extends Thread {
private Socket s;
private HashMap hm;
private String username;

public ServerUserCheck(Socket s, HashMap hm) {
    this.hm = hm;
    this.s = s;
}

@Override
public void run() {
    try {
        InputStream in = s.getInputStream();
        OutputStream out = s.getOutputStream();
        while (true) {
            byte[] bys = new byte[1024];

            int len = in.read(bys);
            username = new String(bys, 0, len);
            if (!hm.containsKey(username)) {
                hm.put(username, s);
                out.write("yes".getBytes());
                break;
            } else {
                out.write("no".getBytes());
            }

        }
        Set keySet = hm.keySet();

        for (String key : keySet) {
            if (key.equals(username)) {
                break;
            }
            String online = username + ":" + "上线了..." + ":" + Configs.MSG_ONLINE + ":" + System.currentTimeMillis();
            Socket s = hm.get(key);
            OutputStream ou = s.getOutputStream();
            ou.write(online.getBytes());

        }
        new ServerThread(hm, s, username).start();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

}
服务端转发信息的线程:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Set;

import Configs.Configs;

public class ServerThread extends Thread {

private HashMap hm;
private Socket s;
private String username;

public ServerThread(HashMap hm, Socket s, String username) {
    this.hm = hm;
    this.s = s;
    this.username = username;

}

@Override
public void run() {
    try {
        InputStream in = s.getInputStream();
        OutputStream out = s.getOutputStream();
        while (true) {
            byte[] bys = new byte[1024];
            int len = in.read(bys);
            String client = new String(bys, 0, len);
            String[] msgs = client.split(":");
            //接收者
            String receiver = msgs[0] ;
            //消息内容
            String msgContent = msgs[1] ;
            //消息类型
            int msgType = Integer.parseInt(msgs[2]) ;

            //拆分消息之后,重新组装消息,约定服务器转发格式
            //发送者:消息内容:消息类型:时间
            long time = System.currentTimeMillis() ;

            if (msgType == Configs.MSG_PRIVATE) {

                Socket s = hm.get(receiver);

                String zfMsg = username + ":" +msgContent + ":" + msgType + ":" + time;
                s.getOutputStream().write(zfMsg.getBytes());
            } else if (msgType == Configs.MSG_PUBLIC) {
                Set keySet = hm.keySet();
                for (String key : keySet) {
                    if (username.equals(key)) {
                        continue;
                    }
                    Socket s = hm.get(key);
                    String zfMsg = username + ":" + msgContent + ":" + msgType + ":" + time;
                    s.getOutputStream().write(zfMsg.getBytes());
                }

            } else if (msgType == Configs.MSG_ONLIST) {
                Set keySet = hm.keySet();
                StringBuffer sb = new StringBuffer();
                int i = 1;
                for (String key : keySet) {
                    if (key.equals(username)) {
                        continue;
                    }
                    sb.append(i++).append(",").append(key).append("\n");

                }
                String zfMsg = username + ":" + sb.toString() + ":" + Configs.MSG_ONLIST + ":" + time;
                Socket s = hm.get(username);
                s.getOutputStream().write(zfMsg.getBytes());

            }else if(msgType==Configs.MSG_EXIT) {
                Set keySet = hm.keySet();
                for(String key:keySet) {
                    if(key.equals(username)) {
                        continue;
                    }
                    Socket ou = hm.get(key);
                    String zfMsg=username+":"+"下线了"+":"+Configs.MSG_EXIT+":"+time;
                    ou.getOutputStream().write(zfMsg.getBytes());
                }
                break;
            }
        }
        hm.get(username).close();
        hm.remove(username);
    } catch (NumberFormatException e) {

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}