聊天室服务端的实现

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

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;
    }

}
时间: 2024-10-14 12:50:00

聊天室服务端的实现的相关文章

goland 简单聊天室服务端

package main import ( "fmt" "net" "strings" "time" ) type Client struct { C chan string //用于发送数据的管道 Name string //用户名 Address string //IP地址 } //保存在线用户 var onLineMap map[string]Client var message = make(chan string)

阅读高手编写的类似QQ聊天的服务端代码业务层设计总结

业务层的代码也应该是面向接口编程,先抽象一个接口或是抽象类,规范一些算法或者功能框架,再在其子类或是实现类中完成具体的方法,易于后期代码的维护. 1.业务层缓存技术 如果数据对实时性要求不高,可以把数据缓存在内存中,提高效率.一般都是利用集合来缓存数据.如下代码: /** * 存放写线程的缓存器 * * @author way */ public class OutputThreadMap { private HashMap<Integer, OutputThread> map; <sp

聊天室-服务端线程处理客户端信息

public class ServerThread extends Thread { //需要处理的socket private Socket socket; //该线程对应的用户信息 private User user; //新建读取信息缓存区 public BufferedReader bufferedReader; //新建写入字符流 public PrintWriter printWriter; //通过构造方法,初始化socket public ServerThread(Socket

h5聊天室web端(仿微博、微信)|h5仿微信网页端|仿微信界面弹窗

html5开发的仿微博.微信聊天web端案例,h5仿微信聊天网页版,采用html5+css3+jquery+swiper+wcPop等技术进行布控架构开发,弹窗插件wcPop.js进行了一次全面api升级,修复编辑器插入表情时光标定位错误bug,新增了上传附件及自定义推送内容,另外也新增了个人名片.上传附件.分享等样式,功能上实现了消息.表情的发送,图片.视频全屏预览. 项目运行图: /* --- 用户设置.Start ---*/ // 联系人/群聊切换 $("body").on(&q

C#编写聊天软件服务端

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.IO; 7 8 namespace SyncChatServer 9 { 10 class User 11 { 12 public TcpClient client { get; private set; } 13 publi

阅读高手编写的类似QQ聊天的服务端代码DAO设计总结

1.数据访问层DAO的设计(已该工程为例) (1)首先定义一个接口,规范算法框架.(若子类和基类有很多公用的东西,则应该设计成抽象类) package com.way.chat.dao public interface UserDao { //注册成功返回用户id public int register(User u); public ArrayList<User> login(User u); public ArrayList<User> refresh(int id); pub

使用Angular和Nodejs搭建聊天室

一,利用Node搭建静态服务器 这个是这个项目的底层支撑部分.用来支持静态资源文件像html, css, gif, jpg, png, javascript, json, plain text等等静态资源的访问.这里面是有一个mime类型的文件映射. mime.js /** * mime类型的 map * @ author Cheng Liufeng * @ date 2014/8/30 * 当请求静态服务器文件的类型 html, css, gif, jpg, png, javascript,

vue + socket.io实现一个简易聊天室

vue + vuex + elementUi + socket.io实现一个简易的在线聊天室,提高自己在对vue系列在项目中应用的深度.因为学会一个库或者框架容易,但要结合项目使用一个库或框架就不是那么容易了.功能虽然不多,但还是有收获.设计和实现思路较为拙劣,恳请各位大大指正. 可以达到的需求 能查看在线用户列表 能发送和接受消息 使用到的框架和库 socket.io做为实时通讯基础 vuex/vue:客户端Ui层使用 Element-ui:客户端Ui组件 类文件关系图 服务端: 客户端: 服

群聊天室中socket的运用 的理解

群聊天室服务端:准备在线Socket列表:list<Socket>sockets;ServerSocket ss; while(ture){Socket s=ss.accept();sockets.add(s);new WorkThread(s).start();}WorkThread{for(int i=0;i<sockets.size();i++){sockets.get(i).getOS().write();}}