ConnectThread
package Chat.Service;
import Chat.common.Message;
import Chat.common.MessageType;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
/**
* @author whlie(true){learn}
* 和客户端保持通信
*/
public class ConnectThread extends Thread {
private Socket socket;
//连接到服务端的用户ID
private String userId;
public ConnectThread( String userId,Socket socket) {
this.socket = socket;
this.userId = userId;
}
public Socket getSocket() {
return socket;
}
@Override
public void run() {
while(true){
System.out.println("客户端"+userId+"与服务器正在通信...");
try {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message message=(Message) ois.readObject();
//根据message的类型做相应的业务处理
if (message.getMesType().equals(MessageType.GET_ONLINE)){
//在线用户列表
System.out.println(message.getSender()+"请求在线用户列表");
String online = Manage.getOnline();
//构建message对象返回给客户端
Message message2 = new Message();
message2.setMesType(MessageType.RET_ONLINE);
message2.setContent(online);
message2.setGetter(message.getSender());
//通过输出流发往客户端
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(message2);
}else if(message.getMesType().equals(MessageType.COMMON_MES)){
//获取目标线程
ConnectThread ct = Manage.get(message.getGetter());
//根据线程得到输出流
ObjectOutputStream oos = new ObjectOutputStream(ct.getSocket().getOutputStream());
//转发,如果不在线可以保存在数据库,实现离线留言
oos.writeObject(message);
}else if(message.getMesType().equals(MessageType.GROUP)){
//遍历管理线程的集合,得到所有线程的socket,把message进行转发
HashMap<String, ConnectThread> hm = Manage.getHm();
Iterator<String> iterator = hm.keySet().iterator();
while(iterator.hasNext()){
//取出在线用户id
String onlineid = iterator.next().toString();
//排除自身
if (!onlineid.equals(message.getSender())){
ObjectOutputStream oos = new ObjectOutputStream
(hm.get(onlineid).getSocket().getOutputStream());
oos.writeObject(message);
}
}
}else if (message.getMesType().equals(MessageType.FILE)){
ObjectOutputStream oos = new ObjectOutputStream(Manage.get(message.getGetter()).getSocket().getOutputStream());
oos.writeObject(message);
} else if(message.getMesType().equals(MessageType.EXIT)){
Manage.remove(message.getSender());
socket.close();
System.out.println(message.getSender()+"已退出登录");
break;
} else{
System.out.println("1");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Manage
package Chat.Service;
import java.util.HashMap;
import java.util.Iterator;
/**
* @author whlie(true){learn}
* 用于管理和客户端之间的通信
*/
public class Manage {
private static HashMap<String,ConnectThread> hm=new HashMap<>();
public static void add(String userId,ConnectThread connectThread){
hm.put(userId,connectThread);
}
public static void remove(String userId){
hm.remove(userId);
}
public static HashMap<String, ConnectThread> getHm() {
return hm;
}
public static ConnectThread get(String userId){
return hm.get(userId);
}
//返回在线用户列表
public static String getOnline(){
//遍历集合,迭代器
Iterator<String> iterator = hm.keySet().iterator();
String online="";
while(iterator.hasNext()){
online += iterator.next().toString()+" ";
}
return online;
}
}
SendtoAll
package Chat.Service;
import Chat.common.Message;
import Chat.common.MessageType;
import Chat.tool.Utility;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
/**
* @author whlie(true){learn}
*/
public class SendtoAll implements Runnable{
private Scanner scanner = new Scanner(System.in);
@Override
public void run() {
while (true){
System.out.println("请输入推送内容:(输入exit退出)");
String news= Utility.readString(100);
if (news.equals("exit")){
break;
}
//构建消息并群发
Message message = new Message();
message.setSender("服务器");
message.setContent(news);
message.setMesType(MessageType.GROUP);
message.setSenderTime(new Date().toString());
System.out.println("服务器推送消息:"+news);
//遍历所有的通信通道的到socket
HashMap<String, ConnectThread> hm = Manage.getHm();
Iterator<String> iterator = hm.keySet().iterator();
while(iterator.hasNext()){
String id = iterator.next().toString();
try {
ObjectOutputStream oos = new ObjectOutputStream(hm.get(id).getSocket().getOutputStream());
oos.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Service
package Chat.Service;
import Chat.common.*;
import java.io.*;
import java.net.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author whlie(true){learn}
* 服务器 等待客户端连接 并保持通信
*/
public class Service {
private ServerSocket ss=null;
/**
* 因为还不会数据库所以使用ConcurrentHashMap代替
* HashM是线程不安全的
* ConcurrentHashMap是线程安全的,解决并发问题
*/
private static ConcurrentHashMap<String,User> sql=new ConcurrentHashMap<String,User>();
//还未实现单点登录
static{
sql.put("100",new User("100","123456"));
sql.put("唐僧",new User("唐僧","123456"));
sql.put("至尊宝",new User("至尊宝","123456"));
sql.put("紫霞仙子",new User("紫霞仙子","123456"));
}
//验证用户登录
public boolean check(String userId,String password){
User user = sql.get(userId);
if (user==null){
return false;
}
if (!user.getPassword().equals(password)){
return false;
}
return true;
}
public Service(){
System.out.println("服务器在9999端口监听...");
try {
ss=new ServerSocket(9999);
//启动推送
new Thread(new SendtoAll()).start();
//因为要一直监听
while(true){
//如果没有连接会阻塞在这里
Socket socket = ss.accept();
//输入流
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
//输出流
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
//读取客户端发送的User对象
User user=(User) ois.readObject();
//用于回复客户端
Message message = new Message();
//验证用户是否存在
if (check(user.getUserId(),user.getPassword())){
message.setMesType(MessageType.LONGIN_SUCCESS);
//将Message回复给客户端
oos.writeObject(message);
//创建一个线程与客户端保持通信
ConnectThread connectThread = new ConnectThread(user.getUserId(),socket);
//启动线程
connectThread.start();
//加入集合
Manage.add(user.getUserId(),connectThread);
}else {
System.out.println("用户"+user.getUserId()+"登录失败");
message.setMesType(MessageType.LONGIN_FAIL);
oos.writeObject(message);
socket.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//如果服务器退出了while说明结束监听,关闭服务器
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ServiceView
package Chat;
import Chat.Service.Service;
/**
* @author whlie(true){learn}
* 启动服务器
*/
public class ServiceView {
public static void main(String[] args) {
new Service();
}
}