public class QQView {
private User u = new User();
private String key = "";//接受用户键盘输入
private boolean loop = true;//控制循环
public static void main(String[] args) {
new QQView().mainMenu();
System.out.println("客户端退出");
}
public void mainMenu() {
while (loop) {
System.out.println("==============欢迎登陆网络通信系统==============");
System.out.println("\t\t1 登录系统");
System.out.println("\t\t9 退出系统");
System.out.print("请输入你的选择: ");
key = Utility.readString(1);
switch (key) {
case "1":
System.out.print("请输入你的用户名: ");
String userId = Utility.readString(50);
System.out.print("请输入你的密码: ");
String password = Utility.readString(50);
//设计一个类,验证用户名密码
if (false) {
System.out.println("==============欢迎(用户 " + userId + " 登录成功)==============");
//进入二级菜单
while (loop) {
System.out.println("\n==============网络通信系统二级菜单(用户 " + userId + " )==============");
System.out.println("\t\t1 显示在线用户列表");
System.out.println("\t\t2 群发消息");
System.out.println("\t\t3 私聊消息");
System.out.println("\t\t4 发送文件");
System.out.println("\t\t9 退出系统");
System.out.print("请输入你的选择: ");
key = Utility.readString(1);
switch (key) {
case "1":
System.out.println("显示在线用户列表");
break;
case "2":
System.out.println("群发消息");
break;
case "3":
System.out.println("私聊消息");
break;
case "4":
System.out.println("发送文件");
break;
case "9":
System.out.println("退出系统");
loop = false;
break;
}
}
} else {
System.out.println("登录失败");
}
break;
case "9":
System.out.println("退出系统");
loop = false;
break;
}
}
}
}
客户端UserClientServer类
该类用于完成用户登录验证和用户注册等功能;
public class UserClientServer {
private User u = new User();
private Socket socket;
public boolean checkUser(String userId, String password) {
//创建一个user对象
u.setUserId(userId);
u.setPassword(password);
boolean b = false;
try {
//连接到服务端
socket = new Socket(InetAddress.getLocalHost(), 9999);
//获取socket关联的对象输出流
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(u);
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message message = (Message) ois.readObject();
if (message.getMessType().equals(MessageType.MESSAGE_LOGIN_SUCCEED)) {
//启动线程,维护socket
ClientConnectServerThread clientConnectServerThread = new ClientConnectServerThread(socket);
clientConnectServerThread.start();
//集合,管理线程
ManageClientConnectServerThread.addClientConnectServerThread(userId, clientConnectServerThread);
b = true;
} else {
//如果连接失败,关闭已开启的socket
socket.close();
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
}
客户端线程类
public class ClientConnectServerThread extends Thread {
//socket属性
private Socket socket;
//构造器socket赋值
public ClientConnectServerThread(Socket socket) {
this.socket = socket;
}
//得到socket
public Socket getSocket() {
return socket;
}
@Override
public void run() {
while (true) {
try {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message message = (Message) ois.readObject();
//做其它的处理
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class QQServer {
private ServerSocket ss = null;
public QQServer() {
//端口可以写在配置文件
try {
System.out.println("服务端在9999端口监听");
ss = new ServerSocket(9999);
while (true) {
Socket socket = ss.accept();
//读取User对象
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
//输出Message对象
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
User u = (User) ois.readObject();
Message message = new Message();
if ("100".equals(u.getUserId()) && "123456".equals(u.getPassword())) {
message.setMessType(MessageType.MESSAGE_LOGIN_SUCCEED);
oos.writeObject(message);
//登陆成功后,创建线程和客户端保持通信
ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, u.getUserId());
serverConnectClientThread.start();
//把该线程对象放入集合中管理
ManageClientThreads.addClientThread(u.getUserId(), serverConnectClientThread);
} else {//登录失败
message.setMessType(MessageType.MESSAGE_LOGIN_FAIL);
oos.writeObject(message);
socket.close();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务端线程类
ManageClientThreads管理线程类
让多个用户登陆服务端,不再是"100","123456"这一个用户
紧接着专门写一个方法验证用户名和密码
单点登录
补充MessageType
在客户端UserClientServer类中定义请求在线用户列表方法,并对服务端发出请求
在客户端的线程类中等待服务端发送数据
服务端代码
获取在线用户列表,即要遍历ManageClientThreads类中的hm集合,将这段遍历集合的代码封装进ManageClientThreads类中的getOnlineUser()方法
在服务端的线程类中接收请求用户列表的消息请求,调用getOnlineUser()方法得到在线用户列表,通过socket将数据返回给客户端
在UserClientServer类中编写一个方法,客户端退出系统,并给服务器发送一个退出系统的message
在服务端响应客户端的请求,接收客户端发送的message,进行处理
在服务端的通信线程中接收这个message并进行转发
在客户端把从服务端转发过来的消息显示
在客户端MessageClientServer类中编写一个方法,并调用;向服务端发送一个请求
在服务端的通信线程中接收这个message并进行转发(群发)
在客户端把从服务端转发过来的消息显示
public class FileClientServer {
/**
* @param src 源文件
* @param dest 把该文件传输到对方的哪个目录
* @param sender 发送用户id
* @param getter 接受用户id
*/
public void sendFileToOne(String src, String dest, String sender, String getter) {
//读取src文件 封装到message对象
Message message = new Message();
message.setMessType(MessageType.MESSAGE_FILE_MES);
message.setSender(sender);
message.setGetter(getter);
message.setSrcPath(src);
message.setDestPath(dest);
//需要将文件读取
BufferedInputStream bis = null;
byte[] fileBytes = new byte[(int) new File(src).length()];//获取文件的大小(Long 字节)
try {
bis = new BufferedInputStream(new FileInputStream(src));
bis.read(fileBytes);
//将文件对应的字节数组设置到message对象
message.setFileBytes(fileBytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//提示信息
System.out.println("\n" + sender + "给 " + getter + " 发送文件:" +
src + " 到对方的电脑目录" + dest);
try {
//发送
ClientConnectServerThread clientConnectServerThread
= ManageClientConnectServerThread.getClientConnectServerThread(sender);
Socket socket = clientConnectServerThread.getSocket();
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端接收这个消息并转发
客户端接收到转发消息,输出到控制台
客户端调用
public class SendNewsToAllServer implements Runnable {
@Override
public void run() {
while (true) {
System.out.print("请输入服务器要推送的新闻[exit退出推送新闻的线程]: ");
String news = Utility.readString(1000);
//构建一个消息
Message message = new Message();
message.setSender("服务器");
message.setContent(news);
message.setMessType(MessageType.MESSAGE_TO_ALL_MES);
message.setSendTime(new Date().toString());
System.out.println("服务器推送消息给所有人 说: " + news);
//遍历当前所有的通信线程,得到Socket,并发送message
Map<String, ServerConnectClientThread> hm = ManageClientThreads.getHm();
Collection<ServerConnectClientThread> serverConnectClientThreads
= hm.values();
Iterator<ServerConnectClientThread> iterator =
serverConnectClientThreads.iterator();
while (iterator.hasNext()) {
ServerConnectClientThread serverConnectClientThread = iterator.next();
Socket socket = serverConnectClientThread.getSocket();
try {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}