day03-3私聊功能
多用户即时通讯系统03
4.编码实现02
4.4功能实现-私聊功能实现
4.4.1思路分析
- 客户端 - 发送者:
- 用户在控制台输入信息,客户端接收内容
- 将消息构建成Messgae对象,通过对应的socket发送给服务器
- 服务器:
- 可以读取到客户端(发送者)发送给某个用户(接收者)的消息
- 从管理线程的集合中,根据messgae对象的信息,获取到接收者的userId,从而获取接收者的socket
- 最后将Message对象转发给指定客户(接收者)
- 客户端 - 接收者:
- 在接收者的线程(通信线程中),读取到发送者的message消息,并显示即可
4.4.2代码实现
1.客户端
1.MessageClientService类
这里新建一个类,专门用来管理聊天(私聊/群聊)的功能
package qqclient.service;
import qqcommon.Message;
import qqcommon.MessageType;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
/**
* @author 李
* @version 1.0
* 该类提供和消息(私聊、群聊)相关的服务方法
*/
public class MessageClientService {
/**
* @param content 内容
* @param senderId 发送用户id
* @param getterId 接收用户id
*/
public void sendMessageToOne(String content, String senderId, String getterId) {
//构建 message
Message message = new Message();
message.setMesType(MessageType.MESSAGE_COMM_MES);//设置消息类型是普通的聊天类型
message.setSender(senderId);
message.setGetter(getterId);
message.setContent(content);
message.setSendTime(new Date().toString());//发送时间也封装到message对象中
System.out.println(senderId + " 对 " + getterId + " 说 " + content);
//发送给服务端
try {//在管理线程的集合中,通过userId来获取线程,通过线程来获取对应的socket,再通过socket获取输出流
ObjectOutputStream oos =
new ObjectOutputStream(ManageClientConnectServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());
oos.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.修改:ClientConnectServerThread类
在该类的run方法中修改业务代码,增加else if语句
else if (message.getMesType().equals(MessageType.MESSAGE_COMM_MES)) {
//接收到的是普通的聊天消息
//就把服务器转发的消息,显示到控制台即可
System.out.println(message.getSendTime() + "\n" + message.getSender()
+ " 对" + message.getGetter() + " 说" + message.getContent());
}

3.修改处:QQView类
- 在类中增加属性messageClientService
private MessageClientService messageClientService = new MessageClientService();//该对象用于私聊/群聊
- 在类中的内层循环中调用messageClientService对象中的方法

case "3":
System.out.println("请输入想聊天的用户号(在线):");
String getterId = Utility.readString(50);
System.out.println("请输入想说的话:(100个字符以内)");
String content = Utility.readString(100);
//编写一个方法,将消息发送给服务端
messageClientService.sendMessageToOne(content,userId,getterId);
break;
2.服务端:
1.修改:ServerConnectClientThread类
- 在该类中增加方法getSocket()
public Socket getSocket() {
return socket;
}
- 在该类中的run方法中增加私聊的业务代码
else if (message.getMesType().equals(MessageType.MESSAGE_COMM_MES)) {
//业务三:客户请求和某用户私聊
//根据message获取getterId,再得到接收者对应的线程
ServerConnectClientThread serverConnectClientThread =
ManageClientThreads.getServerConnectClientThread(message.getGetter());
//得到对应的socket的输出流,将message转发给指定的用户
ObjectOutputStream oos =
new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
oos.writeObject(message);//转发消息,提示:如果客户不在线,可以保存消息到数据库,实现离线留言
}

运行:

2.客户端:登录三个用户菩提老祖、至尊宝、紫霞仙子,使其相互通信:
用户1:

用户2:


用户3:

day03-3私聊功能的更多相关文章
- WUSTOJ的“讨论”和“私聊”功能如何使用
反正我是过了1年多才知道有讨论这个功能,2年多才知道有私聊功能. 不知道大家都是什么时候发现的... 讨论还好,在FAQ界面的下边有提示,但是私聊我真没看到哪儿有提示...是我不小心点进去的. 讨论功 ...
- 第二个 SignalR,可以私聊的聊天室
一.简介 上一次,我们写了个简单的聊天室,接下来,我们来整一个可以私聊的聊天室. SignalR 官方 API 文档 需求简单分析: 1.私聊功能,那么要记录用户名或用户ID,用于发送消息. 2.怎么 ...
- Vue3 + Socket.io + Knex + TypeScript 实现可以私聊的聊天室
前言 下文只在介绍实现的核心代码,没有涉及到具体的实现细节,如果感兴趣可以往下看,在文章最后贴上了仓库地址.项目采用前后端模式,前端使用 Vite + Vue3 + TS:后端使用 Knex + Ex ...
- ios项目里扒出来的json文件
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #000000 } p.p2 { margin: 0.0px 0. ...
- ASP.NET程序开发范例宝典
在整理资料时发现一些非常有用的资料源码尤其是初学者,大部分是平时用到的知识点,可以参考其实现方法,分享给大家学习,但请不要用于商业用途. 如果对你有用请多多推荐给其他人分享. 点击对应章节标题下载本章 ...
- iOS超全开源框架、项目和学习资料汇总(5)AppleWatch、经典博客、三方开源总结篇
完整项目 v2ex – v2ex 的客户端,新闻.论坛.apps-ios-wikipedia – apps-ios-wikipedia 客户端.jetstream-ios – 一款 Uber 的 MV ...
- Github上关于iOS的各种开源项目集合(强烈建议大家收藏,查看,总有一款你需要)
下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITableVie ...
- iOS及Mac开源项目和学习资料【超级全面】
UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...
- 【转】iOS超全开源框架、项目和学习资料汇总
iOS超全开源框架.项目和学习资料汇总(1)UI篇iOS超全开源框架.项目和学习资料汇总(2)动画篇iOS超全开源框架.项目和学习资料汇总(3)网络和Model篇iOS超全开源框架.项目和学习资料汇总 ...
随机推荐
- Java开发学习(十)----基于注解开发定义bean 已完成
一.环境准备 先来准备下环境: 创建一个Maven项目 pom.xml添加Spring的依赖 <dependencies> <dependency> < ...
- springboot配置logback.xml
由于springboot框架自带log4j,因此我们只需配置下logback文件,即可, 在main/resources根目录下,新建logback-spring.xml文件,copy下述代码: &l ...
- Python中使用 for 循环来拿遍历 List 的值
常规版本 简单的 for 循环遍历 x_n = ["x1","x2","x3"] for x in x_n: print(x) >&g ...
- golang拾遗:自定义类型和方法集
golang拾遗主要是用来记录一些遗忘了的.平时从没注意过的golang相关知识. 很久没更新了,我们先以一个谜题开头练练手: package main import ( "encoding ...
- Java通过反射注解赋值
前段时间,领导分配一个统计销售区域汇总的数据,解决方案使用到了反射获取注解,通过注解获取属性或者设置字段属性. 问题描述 查询公司列表,分别是公司id.区域id.区域名称: 公司id 区域id 区域名 ...
- ACWing94.递归实现指数型枚举
https://www.acwing.com/problem/content/description/94/ 题面 \92. 递归实现指数型枚举 从 1∼n 这 n 个整数中随机选取任意多个,输出所有 ...
- 循环数组%操作下的一些解释(对于4.4UVA133的一些解释)
1.循环数组一般不推荐通过建立相同的数组不断叠加来实现,虽然理论上是可行的,但是会浪费极大的空间,特别是对于大数据的情况下,程序一般会马上挂掉 2.循环数组的结构表示中的一种常用形式就是通过取余操作来 ...
- 非root用户linux下安装FFTW
一.环境准备 确保g++可用本次编译是基于 GNU C++ 环境的,因此务必确定g++编译器可用,使用如下命令验证:命令:g++ --version出现类似如下输出则表明编译器可用: 二.下载FFTW ...
- 6.14 YZBOI模拟赛solution
\(6.14\ YZBOI\)模拟赛\(solution\) 本来不想写题解来着...毕竟是自己找的题还是写一写吧 上午为了整活,就把赛制改成\(IOI\)赛制了,于是乎拯救了大家的\(70pts\) ...
- 万答#2,一样的Python代码,为什么可以删表,却不能更新数据
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 问题 运行下面的这段Python代码,却总是无法更新数据: import pym ...