韩顺平--多人在线通信系统
Posted 闲言博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了韩顺平--多人在线通信系统相关的知识,希望对你有一定的参考价值。
https://www.bloghut.cn/questionBank
链接: 面试题库
1、使用技术
- Java面向对象编程
- 网络编程
- 多线程
- IO流
- 集合
2、项目功能
1、用户登录
2、拉取在线用户列表
3、无异常退出(客户端,服务端)
4、思路
5、群聊
6、发文件
7、服务器推送新闻
3、项目效果
服务端
(1)启动服务端
客户端
(1)启动客户端
启动多个客户端
(2)登录成功
这里我登录三个用户
(3) 显示在线用户列表
(4)群发消息
其他用户收到群发消息
(5)私聊消息
被私聊的用户收到消息
(6)发送文件
其他用户收到
(7)离线私聊
发送方
接收方登录上线
4、项目代码
(1)客户端
项目结构
1、QQView 客户端界面类
public class QQView
private boolean loop = true;//控制是否显示菜单
private String key = "";//接收用户的键盘输入
private UserClientService userClientService = new UserClientService();//用于登录服务器、注册用户
private MessageService messageService = new MessageService();
private ClientFileService clientFileService = new ClientFileService();
//显示主菜单
private void mainMenu()
while (loop)
System.out.println("============欢迎登录网络通信系统============");
System.out.println("\\t\\t 1 登录系统");
System.out.println("\\t\\t 9 退出系统");
System.out.print("请输入你的选择:");
key = Utility.readString();
//根据用户输入来处理不同的逻辑
switch (key)
case "1":
System.out.print("请输入用户号:");
String uid = Utility.readString();
System.out.print("请输入密 码:");
String password = Utility.readString();
//这里比较麻烦了,需要到服务端验证
if (userClientService.checkUser(uid,password))
//并移除该用户的离线留言内容
messageService.removeMsg(uid);
System.out.println("============欢迎(用户" + uid + ")登录成功============");
while (loop)
//进入到二级菜单
System.out.println("============网络通信系统二级菜单(用户" + uid + ")============");
System.out.println("\\t\\t 1 显示在线用户列表");
System.out.println("\\t\\t 2 群发消息");
System.out.println("\\t\\t 3 私聊消息");
System.out.println("\\t\\t 4 发送文件");
System.out.println("\\t\\t 9 退出系统");
System.out.print("请输入你的选择:");
key = Utility.readString();
switch (key)
case "1":
userClientService.getUsers(uid);
break;
case "2":
System.out.println("\\n请输入你的群发内容");
String contentAll = Utility.readString();
messageService.sendMsg(contentAll,uid);
break;
case "3":
System.out.println("\\n请输入你要聊天的用户号(在线):");
String getter = Utility.readString();
System.out.println("\\n请输入你要私聊的内容");
String content = Utility.readString();
//发送消息
messageService.sendMsg(content,getter,uid);
break;
case "4":
System.out.print("请输入你想把文件发送给的用户(在线用户):");
getter = Utility.readString();
System.out.print("请输入发送文件的路径(形式如 d:\\\\xx.jpg):");
String src = Utility.readString();
System.out.print("请输入把文件发送到对方的路径(形式如 d:\\\\xx.jpg):");
String dest = Utility.readString();
clientFileService.sendFileToOne(src,dest,uid,getter);
break;
case "9":
loop = false;
System.out.println("客户端退出系统");
userClientService.exit(uid);
break;
default:
System.out.println("输入错误");
else
System.out.println("登录失败");
break;
case "9":
loop = false;
System.out.println("客户端退出系统");
System.exit(0);
break;
default:
System.out.println("输入有误");
public static void main(String[] args)
new QQView().mainMenu();
2、Utility 工具类,接收键盘输入
public class Utility
private static Scanner sc = null;
static
sc = new Scanner(System.in);
public static String readString()
String next = sc.nextLine();
return next;
3、UserClientService 用户请求处理类
public class UserClientService
//因为可能在其他地方需要使用到这个user信息,因此作成成员属性。
private User user = new User();
//因为socket在其他地方也可能使用,因此也做成属性
private Socket socket;
/**
* 根据用户id和密码 到服务器验证该用户是否有效
* @param userId 用户id
* @param pwd 用户密码
* @return 返回值
*/
public boolean checkUser(String userId,String pwd)
boolean flag = false;
user.setUserId(userId);
user.setPassword(pwd);
//连接到服务端,发送user对象
try
//创建socket
socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
//得到ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
//发送user对象
oos.writeObject(user);
//读取服务端回复
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message message = (Message)ois.readObject();
//判断是否登录成功
if(MessageType.MESSAGE_LOGIN_SUCCESS.equals(message.getMsgType()))
//如果有留言信息时,显示出来
if (!("".equals(message.getContent())))
System.out.println("亲,你有离线留言信息哦");
System.out.println(message.getContent());
//创建一个和服务器端保持通信的线程-->创建线程类
ClientConnectServerThread clientConnectServerThread = new ClientConnectServerThread(socket);
//启动客户端线程
clientConnectServerThread.start();
//为了后面客户端的扩展,将线程放到集合中管理
ManageClientConnectServerThread.addClientConnectServerThread(userId,clientConnectServerThread);
flag = true;
else
//如果登录失败,则不能启动和服务器通信的线程,关闭socket
socket.close();
return false;
catch (Exception e)
e.printStackTrace();
return flag;
/**
* 向服务器端请求获取在线用户列表
* @return 在线用户列表
*/
public void getUsers(String userId)
Message message = new Message();
message.setSender(userId);
message.setMsgType(MessageType.MESSAGE_GET_ONLINE_FRIEND);
try
//得到userId 得到线程对象,通过线程得到关联的socket 对应的 ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(ManageClientConnectServerThread
.getClientConnectServerThread(userId)
.getSocket()
.getOutputStream());
//发送一个message,向服务端获取一个在线用户列表
oos.writeObject(message);
catch (Exception e)
e.printStackTrace();
/**
* 退出客户端系统
* @param userId 用户id
*/
public void exit(String userId)
Message message = new Message();
message.setSender(userId);
message.setMsgType(MessageType.MESSAGE_CLIENT_EXIT);
try
//得到userId 得到线程对象,通过线程得到关联的socket 对应的 ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(ManageClientConnectServerThread
.getClientConnectServerThread(userId)
.getSocket()
.getOutputStream());
//发送一个message,向服务端获取一个在线用户列表
oos.writeObject(message);
System.exit(0);
catch (Exception e)
e.printStackTrace();
4、MessageService 消息请求处理类
public class MessageService
/**
* 给指定用户发送内容
* @param content 内容
* @param getter 指定用户
*/
public void sendMsg(String content,String getter,String userId)
Message message = new Message();
message.setMsgType(MessageType.MESSAGE_COMM_MES);
message.setSender(userId);
message.setContent(content);
message.setGetter(getter);
message.setSendTime(new Date().toString());
ObjectOutputStream oos = null;
try
//获取当前用户线程的socket
oos = new ObjectOutputStream(
ManageClientConnectServerThread.getClientConnectServerThread(
userId)
.getSocket()
.getOutputStream());
oos.writeObject(message);
catch (Exception e)
e.printStackTrace();
/**
* 群发内容
* @param content 内容
* @param userId 发送者id
*/
public void sendMsg(String content,String userId)
Message message = new Message();
message.setMsgType(MessageType.MESSAGE_COMM_MES_ALL);
message.setContent(content);
message.setGetter("所有人");
message.setSender(userId);
ObjectOutputStream oos = null;
try
oos = new ObjectOutputStream(
ManageClientConnectServerThread.getClientConnectServerThread(userId).getSocket().getOutputStream());
oos.writeObject(message);
catch (Exception e)
e.printStackTrace();
/**
* 移除用户离线留言的内容
* @param userId 用户id
*/
public void removeMsg(String userId)
try
Message message = new Message();
message.setSender(userId);
message.setMsgType(MessageType.MESSAGE_REMOVE_MSG);
ObjectOutputStream oos = new ObjectOutputStream(ManageClientConnectServerThread.getClientConnectServerThread(userId).getSocket().getOutputStream());
oos.writeObject(message);
catch (Exception e)
e.printStackTrace();
5、ClientFileService 文件请求处理类
public class ClientFileService
/**
* 发送文件
* @param src 源文件
* @param dest 把该文件传输到对方目录
* @param senderId 发送者id
* @param getterId 接收者id
*/
public void sendFileToOne(String src,String dest,String senderId,String getterId)
Message message = new Message();
message.setMsgType(MessageType.MESSAGE_SENDFILE);
message.setSender(senderId);
message.setGetter(getterId);
message.setDest(dest);
message.setSrc(src);
//创建文件数组
int fileLen = (int) new File(src).length();
byte[] fileBytes = new byte[fileLen];
FileInputStream fis = null;
try
fis = new FileInputStream(src);
fis.read(fileBytes);
message.setFileBytes(fileBytes);
message.setFileLen(fileLen);
catch (Exception e)
e.printStackTrace();
finally
try
if (fis != null) fis.close();
catch (Exception e)第22章 多用户即时通信系统