码迷,mamicode.com
首页 > 其他好文 > 详细

聊天室服务端的实现

时间:2017-11-21 23:47:29      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:protected   nec   stat   color   entryset   split   bsp   rom   pre   

该服务端是一个客户端连接进来新建一个线程,性能有待优化。

socket服务端

public class MyServer {
    
    
    private int port;
    private ServerHandler serverHandler; 
    
    public MyServer(int port,ServerHandler serverHandler) throws IOException{
        System.out.println("初始化服务.....");
        this.setPort(port);
        this.setServerHandler(serverHandler);
        ServerSocket ss = new ServerSocket(port);
        System.out.println("创建服务成功.....");
        System.out.println("正在监听"+port+"端口.....");
        while (true) {
            Socket s = ss.accept();
            serverHandler.connectService(s);
            Thread receiveListenerThread =  new Thread(new ReceiveDataListener(serverHandler, s));
            receiveListenerThread.setName(s.getInetAddress().getHostAddress());
            receiveListenerThread.start();
        }
    }
    
    
    public int getPort() {
        return port;
    }
    public void setPort(int port) {
        this.port = port;
    }
    public ServerHandler getServerHandler() {
        return serverHandler;
    }
    public void setServerHandler(ServerHandler serverHandler) {
        this.serverHandler = serverHandler;
    }
    
}

上线通知

/**
 * 上线通知
 * @author huang
 *
 */
public class OnlineNotify implements Runnable{
    
    private String onlineUserName;
    
    public OnlineNotify(String onlineUserName){
        this.onlineUserName = onlineUserName;
    }
    @Override
    public void run() {
        try {            
            Set<Entry<String,Socket>> set = SocketMap.map.entrySet();
            for (Entry<String,Socket> entry : set) {
                Socket s = (Socket) entry.getValue();
                BufferedOutputStream out =new BufferedOutputStream(s.getOutputStream());
                String notifyInfo = "1000|欢迎 "+onlineUserName+" 登入聊天室";
                Tools.sendData(out, notifyInfo);
            }
        } catch (Exception e) {
            
        }
    }

}

接收信息监听线程

/**
 * 接受消息的线程
 * @author huang
 *
 */
public class ReceiveDataListener implements Runnable{
    
    private ServerHandler serverHandler;
    
    private Socket s;
    
    public ReceiveDataListener(ServerHandler serverHandler, Socket s) {
        this.serverHandler = serverHandler;
        this.s = s;
    }

    public void run() {
        while (true) {
            serverHandler.receiveData(s);
        }
    }
    
    
    
}

服务端处理类接口

/**
 * 服务处理接口
 * @author huang
 *
 */
public interface ServerHandler {
    
    /**
     * 建立连接时调用
     * @param s
     */
    public void connectService(Socket s)  throws IOException ;
    
    /**
     * 接收到数据是调用
     * @param s
     * @throws IOException
     */
    public void receiveData(Socket s);
    
    /**
     * 关闭连接时调用
     * @param s
     * @throws IOException
     */
    public void closeConnect(Socket s);
    
    
}

服务端处理接口实现类

public class ServerHandlerImpl implements ServerHandler {
    
    private ServerBiz sb = new ServerBiz();
    
    public void connectService(Socket s) throws IOException {
        
        System.out.println(s.getInetAddress().getHostAddress()+" 连接了服务...");
    }

    public void receiveData(Socket s) {
        
        try {
            BufferedInputStream in = new BufferedInputStream(s.getInputStream());
            String data = Tools.receiveData(in);
            System.out.println("接收到的数据:"+data);
            String[] datas = data.split("\\|");
            switch (Integer.parseInt(datas[0])) {
                case 1000 :
                    System.out.println("客户端发送了登入请求.....");
                    SocketMap.map.put(datas[1], s);
                    sb.login(s,datas[1]);
                    break;
                case 1001:
                    sb.pocketTransmission(datas[1],datas[2]);
                    break;
                case 1002:
                    sb.transpondMessage(datas[1],datas[2],datas[3]);
                    break;
                case 1010:
                    SocketMap.map.remove(datas[1]);
                    sb.userOffLine(datas[1]);
                    s.close();
                default:
                    break;
            }
            
        } catch (Exception e) {
            // TODO: handle exception
        }

    }
    
    public void closeConnect(Socket s) {
        System.out.println(s.getInetAddress().getHostAddress()+"  的客户端断开了连接");
    }

    /**
     * 检查数据的合法性
     * @param data
     * @return
     */
    protected static boolean checkData(String data){
        if(data.indexOf("|") < 0){
            return false;
        }
        String[] datas = data.split("|");
        if(!datas[0].equals("1000") && !datas[0].equals("1001") && !datas[0].equals("1002")){
            return false;
        }
        return true;
    }
}

服务端业务处理类

public class ServerBiz {
    
    public void login(Socket s,String userName)  throws Exception{
        System.out.println("处理用户登入请求....");
        BufferedOutputStream out =new BufferedOutputStream(s.getOutputStream());
        
        Set<Entry<String,Socket>> set = SocketMap.map.entrySet();
        String responseMsg = "0000";
        for (Entry<String,Socket> en : set) {
            responseMsg = responseMsg +"|"+en.getKey();
        }
        System.out.println(responseMsg);
        Tools.sendData(out, responseMsg);
        
        //对在线的所有用户进行广播,提示有人上线
        new Thread(new OnlineNotify(userName)).start();
    }
    
    public void dataTranspond(Socket s) throws Exception{
        
        
    }
    /**
     * 群发
     * @param s
     * @throws Exception 
     */
    public void pocketTransmission(String user,String msg) throws Exception{
        
        Set<Entry<String,Socket>> set = SocketMap.map.entrySet();
        for (Entry<String,Socket> entry : set) {
            Socket s = (Socket) entry.getValue();
            BufferedOutputStream out =new BufferedOutputStream(s.getOutputStream());
            Tools.sendData(out, "1001|【"+user+"】对大家说:"+msg);
        }
    }
    
    /**
     * 用户下线通知
     * @param user
     * @throws Exception 
     */
    public void userOffLine(String user) throws Exception {
        Set<Entry<String,Socket>> set = SocketMap.map.entrySet();
        for (Entry<String,Socket> entry : set) {
            Socket s = (Socket) entry.getValue();
            BufferedOutputStream out =new BufferedOutputStream(s.getOutputStream());
            Tools.sendData(out, "1010|"+user);
            s.close();
        }
        
    }
    
    /**
     * 消息转发
     * @param fromUser 发送者
     * @param toUser 接收者
     * @param msg 消息
     * @throws Exception 
     */
    public void transpondMessage(String fromUser, String toUser, String msg) throws Exception {
        
        Socket s = SocketMap.map.get(toUser);//获取接收者的socket
        BufferedOutputStream out =new BufferedOutputStream(s.getOutputStream());
        String message = "1002|【"+fromUser+"】对你说:"+msg;
        Tools.sendData(out, message);
        
    }

    
}

socket容器

public class SocketMap {
    
    public static Map<String,Socket> map = new HashMap<String,Socket>();
    
}

工具类

public class Tools {
    
    protected static byte[] getMsgLength(int length){
        System.out.println("返回数据");
        byte[] bt = new byte[4];
        bt[0] = (byte) (length/1000);
        bt[1] = (byte) (length%1000/100);
        bt[2] = (byte) (length%100/10);
        bt[3] = (byte) (length%10);
        
        return bt;
    }
    
    public static void sendData(BufferedOutputStream out,String message) throws Exception{
        System.out.println("message:"+message);
        byte[] head = Tools.getMsgLength(message.getBytes("UTF-8").length);
        out.write(head);
        out.flush();
        out.write(message.getBytes("UTF-8"));
        out.flush();
    }
    
    public static String  receiveData(BufferedInputStream in) throws Exception{
        int length = readMsgHead(in);
        System.out.println("接收到的数据长度:"+length);
        byte[] bt = new byte[length];
        in.read(bt);
        String data = new String(bt,"UTF-8");
        return data;
    }
    
    
    
    protected  static int readMsgHead(BufferedInputStream in) throws IOException{
        int length = 0;
        byte[] bt = new byte[4];
        in.read(bt, 0, 4);
        length = bt[0]*1000+bt[1]*100+bt[2]*10+bt[3];
        return length;
    }
    
    
}

 

聊天室服务端的实现

标签:protected   nec   stat   color   entryset   split   bsp   rom   pre   

原文地址:http://www.cnblogs.com/hwyblog/p/7875650.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!