我这里只显示需要添加的代码,其余代码与韩老师写的一样。
这里用户1发短信给用户2
大体思路:1.在服务器接收用户1输入信息ObjectInputStream的时候有两个分支(if-else),
第一,如果在线程池里用户2不存在,就把输入信息保存在concurrentHashMap
第二,如果线程池里存在用户2,就把输入信息通过ObjectOutputStream.WriteObject发给客户端。
2.在服务器,用户2发送登录成功MessageType给客户端的时候,同时把用户1的信息也发出去,通过message.setContent()。
建议自己在想一下,因为很简单,具体代码如下:
1.设定属性.private static ConcurrentHashMap>ofLineDb = new ConcurrentHashMap<>();
2.写方法用来保存内容
public static void dbmessage(String userId,Message message1){
if (!ManageClientThread.getHm().containsKey(userId)){
ArrayList
messages1.add(message1);
ofLineDb.put(userId,messages1);
}
3.服务器对收到的信息进行分流
else if (o1.getMesType().equals(MessageType.MESSAGE_COMM_MES.getNum())){
//把客户端私聊的内容保存在dbmessage方法里的ConcurrentHashMap里
if (!ManageClientThread.getHm().containsKey(o1.getGetter())) {
o1.setContent("\n"+o1.getSender()+"发消息说"+o1.getContent());
QQserver.dbmessage(o1.getGetter(), o1);
}
//传递给客户端,通过需要收到的用户id找到socket
ServerConnectClientThread getserverconnectclietnthread = ManageClientThread.getserverconnectclietnthread(o1.getGetter());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(getserverconnectclietnthread.getSocket().getOutputStream());
objectOutputStream.writeObject(o1);
}
4.在服务器,当用户2登入时,从数组里取出用户1的信息打包过去。
if (ofLineDb.get(o1.getUserId())!=null){
ArrayList
5.客户端里输出
if (ManageClientConnectiServerThread.getccst(message.getGetter())==null){System.out.println(message.getGetter()+"用户已经离线");
}else
{ System.out.println(senderId+"对"+getterId+"说"+content);
}
服务器端的:
public class ServerConnectClientThread extends Thread{
private Socket socket;
private String userId;
//连接到服务端的用户idpublic ServerConnectClientThread(Socket socket, String userId) {
this.socket = socket;
this.userId = userId;
}@Override
public void run() {//这里线程处于rum的状态,可以发送/接送消息
while(true){
System.out.println("服务端和客户端"+userId+"保持通信,读取数据...");
try {
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Object o = objectInputStream.readObject();
Message o1 = (Message) o;
//后面会使用message
//根据message的类型,做相应的业务处理if (o1.getMesType().equals(MessageType.MESSAGE_GET_ONLINEFRIEND.getNum())){
//客户端要在先用户列表
/*
在线用户列表形式100 200
*/
System.out.println(o1.getSender()+"要在线用户列表");
String onlineUser = ManageClientThread.getOnlineUser();
//返回message
//构建一个message对象,返回给客户端
Message message = new Message();
message.setMesType(MessageType.MESSAGE_RET_ONLINEFRIEND.getNum());
message.setContent(onlineUser);
message.setGetter(message.getSender());
//返回给客户端
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(message);
} else if (o1.getMesType().equals(MessageType.MESSAGE_CLIENT_EXIT.getNum())) {//如果客户端退出把socket退出
System.out.println(o1.getSender()+"退出");
//将这个客户端对应线程,从集合中删除
ManageClientThread.removeServerConnectClientThread(o1.getSender());
socket.close();
//关闭链接
//退出线程
break;
} else if (o1.getMesType().equals(MessageType.MESSAGE_COMM_MES.getNum())){
//把客户端私聊的内容保存在dbmessage方法里的ConcurrentHashMap里
if (!ManageClientThread.getHm().containsKey(o1.getGetter())) {
o1.setContent("\n"+o1.getSender()+"发消息说"+o1.getContent());
QQserver.dbmessage(o1.getGetter(), o1);
}else {
//传递给需要收到的用户idServerConnectClientThread getserverconnectclietnthread = ManageClientThread.getserverconnectclietnthread(o1.getGetter());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(getserverconnectclietnthread.getSocket().getOutputStream());
objectOutputStream.writeObject(o1);
}//如果,提示客户不在线,通过保存到数据库达到离线留言
}else if (o1.getMesType().equals(MessageType.MESSAGE_TO_ALL_MES.getNum())){HashMap hm = ManageClientThread.getHm();
Iterator iterator = hm.keySet().iterator();
while (iterator.hasNext()) {
String next = iterator.next();
//取出在线用户id
if (!(next.equals(o1.getSender()))){
//进行转发message
ObjectOutputStream objectOutputStream =
new ObjectOutputStream(hm.get(next).getSocket().getOutputStream());
objectOutputStream.writeObject(o1);
}
}hm.remove(o1.getSender());
}else if (o1.getMesType().equals(MessageType.FILE_TO_ONE_MES.getNum())){
ServerConnectClientThread getserverconnectclietnthread =
ManageClientThread.getserverconnectclietnthread(o1.getGetter());
Socket socket = getserverconnectclietnthread.getSocket();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(o1);
}else {
System.out.println("其他类型的message,暂时不处理");
}} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}}
}public Socket getSocket() {
return socket;
}
}
public class QQserver {
//ConcurrentHashMap,线程安全的HashMap,多线程下是阿暖的
private ServerSocket ss =null;
//创建一个集合,存放多个用户,如果是这些用户登入就认为是合法的
private static HashMap validUsers = new HashMap<>();
private static ConcurrentHashMap>ofLineDb = new ConcurrentHashMap<>();
public static ConcurrentHashMap> getOfLineDb() {
return ofLineDb;
}public static void setOfLineDb(ConcurrentHashMap> ofLineDb) {
QQserver.ofLineDb = ofLineDb;
}static {//在静态代码块,初始化validUsers
//validUsers.put("100",new User("100","123456"));
validUsers.put("200",new User("200","123456"));
validUsers.put("300",new User("300","123456"));
validUsers.put("至尊宝",new User("至尊宝","123456"));
validUsers.put("铺地老祖",new User("菩提老祖","123456"));
}
public static void dbmessage(String userId,Message message1){
if (!ManageClientThread.getHm().containsKey(userId)){ArrayList
客户端的:
public class MessageClientService {/**
*
* @param content内容
* @param senderId发送用户id
* @param getterId接收用户id
*/
public staticvoid sendMessageToOne(String content,String senderId,String getterId){
//构建message
Message message = new Message();
message.setSender(senderId);
message.setGetter(getterId);
message.setContent(content);
message.setMesType(MessageType.MESSAGE_COMM_MES.getNum());
//设置消息类型
message.setSendTime(new Date().toString());
//发送时间设置到message对象if (ManageClientConnectiServerThread.getccst(message.getGetter())==null){System.out.println(message.getGetter()+"用户已经离线");
}else
{ System.out.println(senderId+"对"+getterId+"说"+content);
}
//发送给服务端
try {
ClientConnectServerThread getccst = ManageClientConnectiServerThread.getccst(senderId);
Socket socket = getccst.getSocket();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}}
public static void sendMessageToAll(String content,String senderId){
Message message = new Message();
message.setSender(senderId);
message.setContent(content);
message.setMesType(MessageType.MESSAGE_TO_ALL_MES.getNum());
//设置消息类型群发
message.setSendTime(new Date().toString());
//发送时间设置到message对象
System.out.println(senderId+"对大家说"+content);
//发送给服务端
try {
ClientConnectServerThread getccst = ManageClientConnectiServerThread.getccst(senderId);
Socket socket = getccst.getSocket();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}}
效果:
登入100,发短信
文章图片
登入200发短信
文章图片
文章图片
【p2p|韩顺平30天javaQQ通信作业扩展-完成离线提醒及接收接收】
推荐阅读
- Codelobster(免费的PHP,HTML,CSS,JavaScript编辑器(IDE))
- 如何使用C#在WinForms应用程序中实现Sciter(轻量级HTML和CSS UI引擎)
- 如何在Symfony 3中将Markdown转换为HTML
- 如何在WinForms中使用wkhtmltopdf和C#从HTML生成PDF
- 如何在Symfony 3中使用SnappyBundle(wkhtmltopdf)从HTML创建PDF
- 使用Javascript,HTML和CSS创建C#Windows .NET应用程序
- 20+最佳响应式和开源html电子邮件和新闻通讯模板
- 15个最佳高级工作门户HTML模板
- 前端|Web渗透测试-实战 方法 思路 总结