Java之实现模拟QQ部分功能

目的

运用网络实现QQ的部分功能

主要内容

1.实现私聊
2.实现群聊

具体内容

定义一套规范
用于体现不同的内容
在包下定义一个ChatProtocol类
实现的内容

  • 1.登录 u+ 姓名 u+
  • 2.返回结果 成功1 失败-1
  • 3.私聊 p+ 姓名♥内容 p+
  • 4.群聊 a+ 姓名♥内容 p+
  public interface ChatProtocol {
  //登录
  String LOGIN_FLAG="u+";
  //私聊
  String PRIVATE_FLAG="p+";
  //群聊
  String PUBLIC_FLAG="a+";
  //分隔符
  String SPLIT_FLAG="♥";
  //状态
  String SUCCESS="1";
  String FAILURE="-1";
}

1.实现私聊

定义一个UserManager类,管理所有登录用的信息

 /**
  * 判断某个用户是否已经登录
  */
  public class UserManager {
  //保存所有用户信息
  private Map<String,Socket> users=new HashMap<>();
  /**
   * 判断用户是否已经登录
   */
  public boolean isLogined(String name){
    //遍历数组
    for (String key:users.keySet()){
        if (key.equals(name)){
            return true;
         }
      }
      return false;
   }
  /**
   * 保存当前用户登陆的信息
   */
  public void save(String name,Socket socket){
     users.put(name, socket);
   }
  /**
   * 通过用户名找到对应的socket
   */
  public Socket socketByName(String name){
      return users.get(name);
  }
  /**
   * 通过socket对象找到对应的名称
   */
  public String nameBySocket(Socket socket){
      for (String key:users.keySet()){
        //取出这个key对应的socket对象
        if (socket==users.get(key)){
            return key;
        }
    }
    return null;
    }   
 }

服务器端

  public class Server {
  //用于保存每一个用户对应的姓名和socket
  public static UserManager manager=new UserManager();
  public static void main(String[] args){
      //创建serversocket
      try(ServerSocket ss=new ServerSocket(8888)){
          //监听所有的客户端
          while (true){
              Socket socket=ss.accept();
              //让子线程处理socket
              new ServerThread(socket).start();
          }
      }catch (IOException e){

      }
   }
}

子线程处理每个客户端的输入输出

  class ServerThread extends Thread{
  private Socket socket;
  public ServerThread(Socket socket){
      this.socket=socket;
  }
  @Override
  public void run() {
      }
  }

重写一个run方法,在run方法里面实现私聊

    BufferedReader br=null;
    PrintStream ps=null;
    try {
        //得到对应的输入流
        br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //得到对应的输出流
        ps=new PrintStream(socket.getOutputStream());
        String line=null;
        while ((line=br.readLine())!=null){
            //登录
            if (line.startsWith(ChatProtocol.LOGIN_FLAG)&&line.endsWith(ChatProtocol.LOGIN_FLAG)){
                //获取名字
                //判断这个用户是否已经登录
                if (Server.manager.isLogined(name)){
                    //登录过了,发送给客户端
                    ps.println(ChatProtocol.FAILURE);
                }else{
                    //没有登录过
                    //保存当前登录的用户信息
                    Server.manager.save(name,socket);
                    //发送给客户端
                    ps.println(ChatProtocol.SUCCESS);
                }
            }
            //判断是不是私聊
            else if (line.startsWith(ChatProtocol.PRIVATE_FLAG)&&line.endsWith(ChatProtocol.PRIVATE_FLAG)){
                //获取信息
                String msg=line.substring(2,line.length()-2);
                //分割
                String[] items=msg.split(ChatProtocol.SPLIT_FLAG);
                //用户名
                String name=items[0];
                //聊天内容
                String message=items[1];
                //通过用户名找到对应的socket
                Socket desSocket=Server.manager.socketByName(name);
                PrintStream desPS=new PrintStream(desSocket.getOutputStream());
                //获取当前用户的名称
                String currentName=Server.manager.nameBySocket(socket);
                //发送私聊消息
                desPS.println(currentName+"向你发来私聊:"+message);
            }else{
            //群聊
            }
         }catch(IOException e){
              e.printStackTrace();
         }
       }   
    } 

客户端

  public class Client {
  public static void main(String[] args){
    BufferedReader br=null;
    PrintStream ps=null;
    BufferedReader brServer=null;
    //连接服务器
    try(Socket socket=new Socket("127.0.0.1",8888)) {
        //登录
        //接收终端输入流
        br=new BufferedReader(new InputStreamReader(System.in));
        //发给服务器端的输出流
        ps=new PrintStream(socket.getOutputStream());
        //接收服务器端的输入流
        brServer=new BufferedReader(new InputStreamReader(socket.getInputStream()));
        while (true){
            //接收终端输入
            String line=JOptionPane.showInputDialog("请输入用户名");
            //拼接登陆格式
            String loginStr=ChatProtocol.LOGIN_FLAG+line+ChatProtocol.LOGIN_FLAG;

            ps.println(loginStr);
            //接受服务器端返回的结果
            String result=brServer.readLine();
            //判断登陆结果
            if (result.equals(ChatProtocol.SUCCESS)) {
               System.out.println("登录成功");
               break;
            }else {
                System.out.println("用户名已存在,请重新登录");
            }
        }
        //登录成功
        //开启线程处理服务器端的输入
        new ClientThread(socket).start();
        String line;
        while ((line=br.readLine())!=null){
            //发送给服务器
            ps.println(line);
          }
        } catch (IOException e) {

        }
     }
  }

子线程

  class ClientThread extends Thread{
  private Socket socket;
  public ClientThread(Socket socket){
      this.socket=socket;
  }
  @Override
  public void run() {
      BufferedReader br=null;
      try {
         br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line=null;
        while ((line=br.readLine())!=null){
            System.out.println(line);
        }
    }catch (IOException e){
        System.out.println("网络出错");
    }finally {
        try {
            if (br!=null) {
                br.close();
            }
            if (socket!=null){
                socket.close();
            }
          } catch (IOException e) {
            e.printStackTrace();
           }
         }
       }
     }

再创建一个客户端,实现在一台电脑上私聊

  class Client1 {
  public static void main(String[] args) {
    BufferedReader br = null;
    PrintStream ps = null;
    BufferedReader brServer = null;
    //连接服务器
    try (Socket socket = new Socket("127.0.0.1", 8888)) {
        //登录
        //接收终端输入流
        br = new BufferedReader(new InputStreamReader(System.in));
        //发给服务器端的输出流
        ps = new PrintStream(socket.getOutputStream());
        //发给服务器端的输入流
        brServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        while (true) {
            //接收终端输入
            String line = JOptionPane.showInputDialog("请输入用户名");
            //拼接登陆格式
            String loginStr = ChatProtocol.LOGIN_FLAG + line + ChatProtocol.LOGIN_FLAG;
            ps.println(loginStr);
            //接受服务器端返回的结果
            String result = brServer.readLine();
            //判断登陆结果
            if (result.equals(ChatProtocol.SUCCESS)) {
                System.out.println("登录成功");
                break;
            } else {
                System.out.println("用户名已存在,请重新登录");
            }
        }
        //登录成功
        //开启线程处理服务器端的输入
        new ClientThread(socket).start();
        String line = null;
        while ((line = br.readLine()) != null) {
            //发送给服务器
            ps.println(line);
        }
        } catch (IOException e) {

        }
     }
  }

2.实现群聊

在UsersManager里加allUsers方法

   * 获取所有人的socket对象
   public synchronized Collection<Socket> allUsers(){
       return users.values();
    }

在服务器端的不是私聊的else里加

   //群聊
   //处理数据
   String msg=line.substring(2,line.length()-2);
   //获取当前用户的名称
   String currentName=Server.manager.nameBySocket(socket);
                //遍历用户所有的信息
   Collection<Socket> sockets=Server.manager.allUsers();
   for (Socket s:sockets){
       PrintStream tempps=new PrintStream(s.getOutputStream());
       tempps.println(currentName+"发来群聊:"+msg);

若想在一台电脑上实现群聊,则可以添加多个客户端

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • 目的 通过之前学习了Java语言中的网络编程,今天就来实现QQ内部的相应聊天功能(群聊、登录功能、群聊) 相关技术...
    黑铁选手阅读 2,121评论 0 2
  • 计算机网络概述 网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据传输。 按照计算机网络的定义,通过一定...
    蛋炒饭_By阅读 1,209评论 0 10
  • 今天,我读了一本让我受益匪浅的书,书的名字叫《钻进电脑里的孩子》,我深有感触。 主人公是一个小男孩儿,他的名字叫奇...
    宇淼阅读 305评论 0 3
  • 写在前面 本着对古人的好奇,读完《明朝那些事》之后,对历史上的人物有种极强的求知欲,想要去了解他们的经历,当然现存...
    青松pzq阅读 1,876评论 0 0
  • 这为什么人都是这样呢他心里想着什么啊作为何光是嘴巴说的这么好但是没有人做的到为何家中就那么痛苦而且是心情烦躁没有人...
    liuwenshun阅读 146评论 0 0