两个工程------客户端 服务端
1.总览
1.1客户端工程
1.2 服务端工程
2.客户端工程代码
2.1 ClientMain
package com.weiwei.qq.main;
import com.weiwei.qqclient.view.QQView;
public class ClientMain {
public static void main(String[] args) {
new QQView().mainMenu();
}
}
2.2 ClientConnectionServerThread
package com.weiwei.qqclient.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import com.weiwei.qqcommon.Message;
import com.weiwei.qqcommon.MessageType;
public class ClientConnectionServerThread extends Thread{
//该线程必须持有Socket
private Socket socket;
//构造方法目的是可以接收一个传过来的socket,赋给当前类的socket
public ClientConnectionServerThread(Socket socket) {
this.socket = socket;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
//因为线程需要在后台和服务器保持通信,因此while循环
while(true){
//客户端的线程是负责读取从服务器端发来的消息
try {
ObjectInputStream objin = new ObjectInputStream(socket.getInputStream());
Message msg=(Message)objin.readObject();//如果服务器没有发message过来,线程会阻塞在这里
//判断客户端返回的msg类型
/**
* 显示在线用户列表
*/
if(msg.getMesType().equals(MessageType.MESSAGE_RETURN_ONLINE)){
//返回的是在线用户数据,取出并显示
//规定在线用户列表是仅显示用户id 空格隔开
String[] onlineusers = msg.getContent().split(",");
System.out.println("======当前用户在线人数"+onlineusers.length+"人======");
for(int i=0;i<onlineusers.length;i++){
System.out.println("用户:"+onlineusers[i]);
}
}
/**
*
* 显示私发消息
*/
if(msg.getMesType().equals(MessageType.MESSAGE_COMM_MES)){
//把服务器转发来的消息显示出来
System.out.println("\n"+msg.getSender()+"对你说:"+msg.getContent()+"\t\t"+msg.getSendTime());
}
/**
*显示群发消息
*
*
*/
if(msg.getMesType().equals(MessageType.MESSAGE_TOALL)){
//把服务器转发来的消息显示出来
System.out.println("\n"+msg.getSender()+"对大家说:"+msg.getContent()+"\t\t"+msg.getSendTime());
}
/**
*
* 显示文件
*
*/
if(msg.getMesType().equals(MessageType.MESSAGE_FILE)){
//把服务器转发来的消息显示出来
System.out.println("\n"+msg.getSender()+"给你发来了一个文件("+msg.getSrc()
+") 到我的电脑的目录("+msg.getDestination()+") \t\t"+msg.getSendTime());
//取出message中的文件字节数组,通过输出流写入到磁盘
FileOutputStream fileout=new FileOutputStream(new File(msg.getDestination()));
fileout.write(msg.getFileBytes());
fileout.close();
System.out.println("\n 自动保存文件成功");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2.3 FileService
package com.weiwei.qqclient.service;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.weiwei.qqcommon.Message;
import com.weiwei.qqcommon.MessageType;
/**
* 该类完成文件传输
*
*/
public class FileService {
/**
*
* src 源文件 destination 传输到对方哪个目录 senderid 发送用户id getterid 接收用户id
*/
public void sendFileToOne(String src, String destination, String senderid, String getterid) {
//创建message对象
Message message = new Message();
message.setMesType(MessageType.MESSAGE_FILE);
message.setSender(senderid);
message.setGetter(getterid);
message.setDestination(destination);
message.setSrc(src);
message.setSendTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));// 发送时间
//读取文件
File file = new File(src);
FileInputStream filein=null;
byte[] fileBytes=new byte[(int)file.length()];
try {
filein=new FileInputStream(file);
filein.read(fileBytes);//将src文件读入到程序的字节数组
//将文件对应的字节数组设置message
message.setFileBytes(fileBytes);
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭
try {
filein.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//提示信息
System.out.println("\n"+senderid+"给"+getterid+"发送文件:"+src+"到对方的电脑的目录"+destination);
//发送message
try {
OutputStream outputStream = ManageClientConnServerThread.getThread(senderid).getSocket()
.getOutputStream();
ObjectOutputStream objectout = new ObjectOutputStream(outputStream);
objectout.writeObject(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.4 ManageClientConnServerThread
package com.weiwei.qqclient.service;
import java.util.HashMap;
/**
*
* 管理客户端连接到服务器端的线程的类
*
*/
public class ManageClientConnServerThread {
//把多个线程放入到一个HashMap集合,key就是用户id,value就是线程
private static HashMap<String,ClientConnectionServerThread> hm=new HashMap<>();
//将某个线程加入到hashmap
public static void addThread(String userid,ClientConnectionServerThread thread){
hm.put(userid, thread);
}
//通过userid可以得到对应线程
public static ClientConnectionServerThread getThread(String userid){
return hm.get(userid);
}
}
2.5 UserClientService
package com.weiwei.qqclient.service;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.weiwei.qqcommon.Message;
import com.weiwei.qqcommon.MessageType;
import com.weiwei.qqcommon.User;
import com.weiwei.utils.Utils;
/**
* 完成用户登录验证功能
*
*
*/
public class UserClientService {
private User user = new User();
private Socket socket;
// 根据userid和password到服务器验证该用户是否合法
public boolean checkUser(String userid, String pwd) {
user.setUserid(userid);
user.setPassword(pwd);
boolean b = false;
try {
// 连接到服务器,发送user对象
socket = new Socket(InetAddress.getLocalHost(), 9999);
// 得到socket输出流
OutputStream outputStream = socket.getOutputStream();
// 创建可以发送对象的输出流
ObjectOutputStream objout = new ObjectOutputStream(outputStream);
// 发送user对象
objout.writeObject(user);
// 读取从服务端回复的message对象
ObjectInputStream objin = new ObjectInputStream(socket.getInputStream());
Message msg = (Message) objin.readObject();
if (msg.getMesType().equals(MessageType.MESSAGE_LOGIN_SUCCEED)) {// 登录成功
// 创建一个和服务器保持通信的线程,需要创建一个类ClientConnectionServerThread
ClientConnectionServerThread cnServerThread = new ClientConnectionServerThread(socket);
cnServerThread.start();
// 为了客户端的扩展性,将线程放入到集合管理
ManageClientConnServerThread.addThread(userid, cnServerThread);
b = true;
} else {
// 如果登录失败,就不能启动和服务器通信的线程,关闭socket
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
/**
*
* 向服务器端请求在线用户列表
*
*/
public void onlinePeople() {
// 向服务器发送一个message,请求在线用户列表
Message msg = new Message();
msg.setMesType(MessageType.MESSAGE_GET_ONLINE);
msg.setSender(user.getUserid());
// 发送给服务器
// 得到当前线程的socket对应的ObjectOutputStream对象
ClientConnectionServerThread thread = ManageClientConnServerThread.getThread(user.getUserid());// 拿到当前线程
try {
// 得到当前线程的socket的OutputStream对象
OutputStream outputStream = thread.getSocket().getOutputStream();
// 得到发送对象的输出流
ObjectOutputStream objectout = new ObjectOutputStream(outputStream);
// 发送给服务器
objectout.writeObject(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 退出客户端,并给服务端发送一个退出系统的message对象
*/
public void exit() {
Message message = new Message();
message.setMesType(MessageType.MESSAGE_CLIENT_EXIT);
message.setSender(user.getUserid());
// 发送message
try {
ObjectOutputStream objout = new ObjectOutputStream(socket.getOutputStream());
objout.writeObject(message);
System.out.println(user.getUserid() + "已退出系统");
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 私聊消息
*
*
*/
public void siliao() {
// 得到用户聊天的另一用户id
String getterid = Utils.getString("请输入想聊天的用户(在线):");
// 得到用户输入的信息
String chatinfo = Utils.getString("请输入聊天内容:");
Message message = new Message();
message.setMesType(MessageType.MESSAGE_COMM_MES);
message.setSender(user.getUserid());
message.setGetter(getterid);
message.setContent(chatinfo);
message.setSendTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));// 发送时间
System.out.println(user.getUserid() + "对" + getterid + "说:" + chatinfo);
// 发送message给服务端
try {
OutputStream outputStream = ManageClientConnServerThread.getThread(user.getUserid()).getSocket()
.getOutputStream();
ObjectOutputStream objectout = new ObjectOutputStream(outputStream);
objectout.writeObject(message);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* 群发消息
*
*
*/
public void qunfa() {
// 得到用户输入的信息
String chatinfo = Utils.getString("请输入群发内容:");
Message message = new Message();
message.setMesType(MessageType.MESSAGE_TOALL);
message.setSender(user.getUserid());
message.setContent(chatinfo);
message.setSendTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));// 发送时间
System.out.println(user.getUserid() + "对所有人说:" + chatinfo);
// 发送message给服务端
try {
OutputStream outputStream = ManageClientConnServerThread.getThread(user.getUserid()).getSocket()
.getOutputStream();
ObjectOutputStream objectout = new ObjectOutputStream(outputStream);
objectout.writeObject(message);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发送文件
*
*/
public void sendfilm() {
String src = Utils.getString("请输入您要发送的文件路径(格式:F:\\a\\...):");
String getterid = Utils.getString("请输入您要发送的人(在线):");
String destination = Utils.getString("请输入对方接收保存的路径:");
FileService fileService = new FileService();
fileService.sendFileToOne(src, destination, user.getUserid(), getterid);
}
}
2.6 QQView
package com.weiwei.qqclient.view;
import com.weiwei.qqclient.service.UserClientService;
import com.weiwei.utils.Utils;
/**
*
* 客户端菜单界面
*
*/
public class QQView {
/**
* 显示主菜单
*/
private boolean loop = true;
private int number = 0;
private UserClientService userclientservice=new UserClientService();
public void mainMenu() {
while (loop) {
System.out.println("=======欢迎使用通讯聊天系统=======");
System.out.println("\t 1 登录系统");
System.out.println("\t 9 退出系统");
number = Utils.getNumber("请输入菜单按键:");// 得到一个数字
// 根据输入的数字处理不同的逻辑
switch (number) {
case 1:
String userid = Utils.getString("请输入用户名:");//得到一个用户名
String password = Utils.getString("请输入密码:");//得到一个密码
//需要服务端验证密码是否正确
boolean checkUser = userclientservice.checkUser(userid, password);
if(checkUser){
//登录成功
//进入二级菜单
while(loop){
System.out.println("=======欢迎用户("+userid+")使用聊天系统=======");
System.out.println("\t 1 显示在线用户列表");
System.out.println("\t 2 私发消息");
System.out.println("\t 3 群发消息");
System.out.println("\t 4 发送文件");
System.out.println("\t 9 退出");
number= Utils.getNumber("请输入菜单按键:");
switch(number){
case 1:
//显示在线用户列表
userclientservice.onlinePeople();
break;
case 2:
//私聊
userclientservice.siliao();
break;
case 3:
//群发消息
userclientservice.qunfa();
break;
case 4:
//发送文件
userclientservice.sendfilm();
break;
case 9:
//退出
userclientservice.exit();
loop=false;
break;
default:
System.out.println("您输入有误,请重新输入菜单数字按钮");
break;
}
}
}else{//登录失败
System.out.println("用户名或密码不正确,请重新登录");
}
break;
case 9:
System.out.println("您已退出聊天系统");
loop=false;
break;
default:
System.out.println("您输入有误,请重新输入菜单数字按钮");
break;
}
}
}
}
2.7 Message
package com.weiwei.qqcommon;
import java.io.Serializable;
/**
*
* 表示客户端和服务器通信时的消息对象
*
*/
public class Message implements Serializable{
private static final long serialVersionUID=1L;//增强序列化兼容性
private String sender;//发送者
private String getter;//接受者
private String content;//消息内容
private String sendTime;//发送时间
private String mesType;//消息类型[可以在接口定义消息类型]
//扩展文件消息
private byte[] fileBytes;
private int filelen=0;
private String destination;//将文件传输到哪里
private String src;//源文件路径
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getGetter() {
return getter;
}
public void setGetter(String getter) {
this.getter = getter;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getSendTime() {
return sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getMesType() {
return mesType;
}
public void setMesType(String mesType) {
this.mesType = mesType;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public byte[] getFileBytes() {
return fileBytes;
}
public void setFileBytes(byte[] fileBytes) {
this.fileBytes = fileBytes;
}
public int getFilelen() {
return filelen;
}
public void setFilelen(int filelen) {
this.filelen = filelen;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
}
2.8 MessageType
package com.weiwei.qqcommon;
public interface MessageType {
/*
* 在接口中定义了一些常量
* 不同的常量的值,表示不同的消息类型
*/
String MESSAGE_LOGIN_SUCCEED="1";//表示登录成功
String MESSAGE_LOGIN_FAIL="2";//表示登录失败
String MESSAGE_COMM_MES="3";//普通信息包
String MESSAGE_GET_ONLINE="4";//要求返回在线用户列表
String MESSAGE_RETURN_ONLINE="5";//返回在线用户列表
String MESSAGE_CLIENT_EXIT="6";//客户端请求退出
String MESSAGE_TOALL="7";//群发消息
String MESSAGE_FILE="8";//文件消息
}
2.9 User
package com.weiwei.qqcommon;
import java.io.Serializable;
/**
*
* 表示一个用户信息
* 实现序列化
*/
public class User implements Serializable{
private static final long serialVersionUID=1L;//增强序列化兼容性
private String userid;//用户id
private String password;//用户密码
public User(){
}
public User(String userid, String password) {
super();
this.userid = userid;
this.password = password;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2.10 Utils
package com.weiwei.utils;
import java.util.Scanner;
public class Utils {
/**
* 键盘输入得到一个数字
*/
public static int getNumber(String string) {
int number=0;
try{
System.out.println(string);
Scanner sc=new Scanner(System.in);
number = sc.nextInt();
//如果用户输入得不是数字,需要异常处理
}catch(Exception e){
System.out.println("您输入有误,请重新输入");
getNumber(string);
}
return number;
}
/**
* 键盘输入得到一个字符串
*/
public static String getString(String string) {
System.out.println(string);
// 创建键盘录入对象
String info="";
Scanner sc = new Scanner(System.in);
info = sc.nextLine();
if(info.length()==0){
System.out.println("输入不能为空,请重新输入:");
getString(string);
}
return info;
}
}
3.服务端工程
3.1 Message
package com.weiwei.qqcommon;
import java.io.Serializable;
/**
*
* 表示客户端和服务器通信时的消息对象
*
*/
public class Message implements Serializable{
private static final long serialVersionUID=1L;//增强序列化兼容性
private String sender;//发送者
private String getter;//接受者
private String content;//消息内容
private String sendTime;//发送时间
private String mesType;//消息类型[可以在接口定义消息类型]
//扩展文件消息
private byte[] fileBytes;
private int filelen=0;
private String destination;//将文件传输到哪里
private String src;//源文件路径
public byte[] getFileBytes() {
return fileBytes;
}
public void setFileBytes(byte[] fileBytes) {
this.fileBytes = fileBytes;
}
public int getFilelen() {
return filelen;
}
public void setFilelen(int filelen) {
this.filelen = filelen;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getGetter() {
return getter;
}
public void setGetter(String getter) {
this.getter = getter;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getSendTime() {
return sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getMesType() {
return mesType;
}
public void setMesType(String mesType) {
this.mesType = mesType;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
3.2 MessageType
package com.weiwei.qqcommon;
public interface MessageType {
/*
* 在接口中定义了一些常量
* 不同的常量的值,表示不同的消息类型
*/
String MESSAGE_LOGIN_SUCCEED="1";//表示登录成功
String MESSAGE_LOGIN_FAIL="2";//表示登录失败
String MESSAGE_COMM_MES="3";//普通信息包
String MESSAGE_GET_ONLINE="4";//要求返回在线用户列表
String MESSAGE_RETURN_ONLINE="5";//返回在线用户列表
String MESSAGE_CLIENT_EXIT="6";//客户端请求退出
String MESSAGE_TOALL="7";//群发消息
String MESSAGE_FILE="8";//文件消息
}
3.3 User
package com.weiwei.qqcommon;
import java.io.Serializable;
/**
*
* 表示一个用户信息
* 实现序列化
*/
public class User implements Serializable{
private static final long serialVersionUID=1L;//增强序列化兼容性
private String userid;//用户id
private String password;//用户密码
public User(String userid, String password) {
super();
this.userid = userid;
this.password = password;
}
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
3.4 ManageServerConnClientThread
package com.weiwei.qqserver.service;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/**
*
* 管理服务器与客户端通信的线程的类
*
*/
public class ManageServerConnClientThread {
//把多个线程放入到一个HashMap集合,key就是用户id,value就是线程
private static HashMap<String,ServerConnectionClientThread> hm=new HashMap<>();
//将某个线程加入到hashmap
public static void addThread(String userid,ServerConnectionClientThread thread){
hm.put(userid, thread);
}
//通过userid可以得到对应线程
public static ServerConnectionClientThread getThread(String userid){
return hm.get(userid);
}
/**
*
* 返回在线用户列表
*
*
*/
public static String getOnlineUser(){
//遍历hashmap集合的key,使用迭代器方法
Set<String> keySet = hm.keySet();//得到键的集合
Iterator<String> iterator = keySet.iterator();//得到迭代器
String onlineUserlist="";
while(iterator.hasNext()){
onlineUserlist=onlineUserlist+iterator.next()+",";
if(!iterator.hasNext()){
onlineUserlist=onlineUserlist.substring(0, onlineUserlist.lastIndexOf(","));
}
}
return onlineUserlist;
}
/**
* 从集合中移除某个线程对象
*/
public static void remove(String userid){
hm.remove(userid);
}
/**
* 返回一个hm
*/
public static HashMap<String,ServerConnectionClientThread> getHm(){
return hm;
}
}
3.5 QQServerService
package com.weiwei.qqserver.service;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
import com.weiwei.qqcommon.Message;
import com.weiwei.qqcommon.MessageType;
import com.weiwei.qqcommon.User;
/**
* 服务器在监听9999,等待客户端连接,并保持通信
*
*
*/
public class QQServerService {
private ServerSocket serversocket = null;
// 创建一个集合,存放多个用户,如果是这些用户登录,就认为我合法
//ConcurrentHashMap专门处理并发,线程安全,HashMap多线程下不安全
private static ConcurrentHashMap<String, User> validUsers = new ConcurrentHashMap<String, User>();
static {// 在静态代码块初始化validUsers
validUsers.put("张三", new User("张三", "123456"));
validUsers.put("李四", new User("李四", "123456"));
validUsers.put("王五", new User("王五", "123456"));
validUsers.put("赵六", new User("赵六", "123456"));
validUsers.put("鲁班", new User("鲁班", "123456"));
validUsers.put("小乔", new User("小乔", "123456"));
validUsers.put("貂蝉", new User("貂蝉", "123456"));
}
public QQServerService(){
//注意:端口可以写在配置文件
try{
System.out.println("服务器在9999端口监听.....");
serversocket=new ServerSocket(9999);
while(true){//当和某个客户端连接后,会继续监听
//接收到客户端的socket
Socket socket = serversocket.accept();//如果没有客户端连接,则会阻塞在这
ObjectInputStream objin = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objout = new ObjectOutputStream(socket.getOutputStream());
User user=(User)objin.readObject();
//验证用户
boolean checkUser = checkUser(user.getUserid(),user.getPassword());
//创建一个Message对象,准备回复客户端
Message msg=new Message();
if(checkUser){//登录成功
msg.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);
//将message对象回复给客户端
objout.writeObject(msg);
//创建一个线程,和客户端保持通信
ServerConnectionClientThread connectionClientThread = new ServerConnectionClientThread(socket,user.getUserid());
//启动该线程
connectionClientThread.start();
//把该线程对象放入到一个集合中,进行管理
ManageServerConnClientThread.addThread(user.getUserid(), connectionClientThread);
}else{//登录失败
System.out.println("用户id="+user.getUserid()+" password="+user.getPassword()+"验证失败");
msg.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
objout.writeObject(msg);
//登录失败,关闭socket
socket.close();
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
//如果服务器退出了while循环,因此需要关闭serversocket
try {
serversocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 验证用户是否有效
*/
private boolean checkUser(String userid, String password) {
User user = validUsers.get(userid);
if (user == null) {// 说明不存在该用户,用户名错误
return false;
}
if(!user.getPassword().equals(password)){//密码错误
return false;
}else{
return true;
}
}
}
3.6 ServerConnectionClientThread
package com.weiwei.qqserver.service;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import com.weiwei.qqcommon.Message;
import com.weiwei.qqcommon.MessageType;
public class ServerConnectionClientThread extends Thread {
// 该线程必须持有Socket
private Socket socket;
private String userid;
// 构造方法目的是可以接收一个传过来的socket,赋给当前类的socket
public ServerConnectionClientThread(Socket socket, String userid) {
this.socket = socket;
this.userid = userid;
}
public Socket getsocket() {
return socket;
}
@Override
public void run() {
// 因为线程需要在后台和客户端保持通信,因此while循环
while (true) {
// 服务端的线程是负责读取从客户端发来的消息
try {
System.out.println("服务端和客户端:" + userid + "正在保持通讯....");
ObjectInputStream objin = new ObjectInputStream(socket.getInputStream());
Message msg = (Message) objin.readObject();// 读取客户端发来的message对象
// 判断客户端发来msg类型
/**
* 服务器返回在线用户列表
*/
if (msg.getMesType().equals(MessageType.MESSAGE_GET_ONLINE)) {
// 客户端要在线用户列表
/*
* 在线用户列表形式 userid ,隔开
*/
System.out.println(msg.getSender() + "请求在线用户列表");
String onlineUser = ManageServerConnClientThread.getOnlineUser();
// 返回message对象给客户端
// 构建一个message对象
Message message2 = new Message();
message2.setMesType(MessageType.MESSAGE_RETURN_ONLINE);
message2.setContent(onlineUser);
message2.setGetter(msg.getSender());
// 写入到数据通道,返回给客户端
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(message2);
;
}
/**
* 服务器关闭线程
*/
if (msg.getMesType().equals(MessageType.MESSAGE_CLIENT_EXIT)) {
System.out.println(msg.getSender() + "退出");
ManageServerConnClientThread.remove(userid);
socket.close();
break;
}
/**
* 服务器转发私聊消息
*/
if (msg.getMesType().equals(MessageType.MESSAGE_COMM_MES)) {
// 根据msg获取到getterid,得到接受者对应的线程
String getterid = msg.getGetter();
OutputStream outputStream = ManageServerConnClientThread.getThread(getterid).getsocket()
.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(msg);
}
/**
* 服务器转发群发消息
*
*/
if (msg.getMesType().equals(MessageType.MESSAGE_TOALL)) {
//遍历管理线程的集合,把所有的线程的socket都得到
HashMap<String, ServerConnectionClientThread> hm = ManageServerConnClientThread.getHm();
Iterator<String> iterator = hm.keySet().iterator();
while(iterator.hasNext()){
String onlineuserid = iterator.next();
if(!onlineuserid.equals(msg.getSender())){//排除群发消息自己给自己
//进行转发
OutputStream outputStream = ManageServerConnClientThread.getThread(onlineuserid).getsocket()
.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(msg);
}
}
}
/**
*
* 文件消息
*
*/
if(msg.getMesType().equals(MessageType.MESSAGE_FILE)){
//进行转发
OutputStream outputStream = ManageServerConnClientThread.getThread(msg.getGetter()).getsocket()
.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
3.7 ServerMain
package com.weiwei.server.main;
import com.weiwei.qqserver.service.QQServerService;
public class ServerMain {
public static void main(String[] args) {
new QQServerService();
}
}