1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Java网络编程——多人聊天室

Java网络编程——多人聊天室

时间:2018-08-19 11:51:49

相关推荐

Java网络编程——多人聊天室

多用户即时通信系统

需求分析:

1、用户登录

2、拉取在线用户列表

3、无异常退出

4、私聊

5、群聊

6、发送文件

7、服务器推送新闻

多用户登录

老韩的课程讲的真的很清楚:

关于Java多线程的文章:/Charzous/article/details/109283697?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162558274616780271528566%2522%252C%2522scm%2522%253A%25220713.130102334.pc%255Fall.%2522%257D&request_id=162558274616780271528566&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-11-109283697.first_rank_v2_pc_rank_v29&utm_term=%E6%8A%8Asocket%E6%94%BE%E5%88%B0%E7%BA%BF%E7%A8%8B&spm=1018.2226.3001.4187

公共类:

Message类

package www.study.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 messagetype;//消息类型public Message(){}public static long getSerialVersionUID() {return SerialVersionUID;}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 getMessagetype() {return messagetype;}public void setMessagetype(String messagetype) {this.messagetype = messagetype;}}

MessageType类

package www.study.qqcommon;public interface MessageType {String MESSAGE_LOGIN_SUCCEED = "1";//登录成功String MESSAGE_LOGIN_FATL = "2";//登录失败}

User类

package www.study.qqcommon;import java.io.Serializable;public class User implements Serializable {private static final long serialVersionUID = 1L;private String userid;private String password;public User(String userid, String password) {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;}}

服务器端:

QQServe类

package www.study.qqservice;import www.study.qqcommon.Message;import www.study.qqcommon.MessageType;import www.study.qqcommon.User;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import .ServerSocket;import .Socket;import java.util.HashMap;/*** 充当服务器,监听9999端口,等待客户端连接,保持通信*/public class QQServer {private ServerSocket serverSocket=null;//创建一个集合,存放用户信息private static HashMap<String,User> users = new HashMap<>();static {users.put("100",new User("100","123"));users.put("123",new User("123","123"));users.put("哈哈",new User("哈哈","123"));users.put("嘎嘎",new User("嘎嘎","123"));}//验证用户登录private boolean checkUser(String userid,String password){User user = users.get(userid);if(user==null){return false;}if(!user.getPassword().equals(password)){return false;}return true;}public QQServer(){try{System.out.println("服务器端正在监听9999端口...");serverSocket = new ServerSocket(9999);while (true){//会持续监听Socket socket = serverSocket.accept();//读取输入ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());User u =(User)objectInputStream.readObject();ObjectOutputStream objectOutputStream=new ObjectOutputStream(socket.getOutputStream());//创建回复客户端的消息Message ms = new Message();if(checkUser(u.getUserid(), u.getPassword())){ms.setMessagetype(MessageType.MESSAGE_LOGIN_SUCCEED);objectOutputStream.writeObject(ms);//创建一个线程和客户端保持通信ServerConnectClientThread serverConnectClientThread =new ServerConnectClientThread(socket,u.getUserid());//启动该线程serverConnectClientThread.start();//将线程放入到集合中管理ManageClientThread.addSeverConnectClientThread(u.getUserid(),serverConnectClientThread);}else{System.out.println("用户 id=" + u.getUserid() + " pwd=" + u.getPassword() + " 验证失败");ms.setMessagetype(MessageType.MESSAGE_LOGIN_FATL);objectOutputStream.writeObject(ms);//关闭socketsocket.close();}}}catch (Exception e){e.printStackTrace();}finally {//如果退出while循环,说明服务器不在监听,关闭ServerSockettry {serverSocket.close();}catch (Exception e){e.printStackTrace();}}}}

ManageClientThread类

package www.study.qqservice;import java.util.HashMap;/*** 用于管理和客户端通信的线程*/public class ManageClientThread {//我们把多个线程放入到一个hashmap中public static HashMap<String,ServerConnectClientThread> hm = new HashMap<>();//添加线程public static void addSeverConnectClientThread(String userid,ServerConnectClientThread serverConnectClientThread){hm.put(userid,serverConnectClientThread);}//通过userid得到对应线程public static ServerConnectClientThread getSeverConnectClientThread(String userid){return hm.get(userid);}}

ServerConnectClientThread类

package www.study.qqservice;import www.study.qqcommon.Message;import java.io.ObjectInputStream;import .Socket;/*** 该类的对象和某个客户端保持通信*/public class ServerConnectClientThread extends Thread{private Socket socket;private String userid;public ServerConnectClientThread(Socket socket,String userid){this.socket = socket;this.userid = userid;}@Overridepublic void run(){//这里的线程处于run的状态,可以接收、发送消息while (true){try {System.out.println("服务器端和客户端"+userid+"保持通信,读取数据...");ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());Message ms =(Message) objectInputStream.readObject();}catch (Exception e){e.printStackTrace();}}}}

客户端

QQView

package www.study.qqClient.view;import www.study.qqClient.service.UserClientService;import java.util.Scanner;public class QQView {private boolean loop = true; //控制是否显示菜单private String key = ""; //用户选择操作private UserClientService userClientService= new UserClientService();//用于用户的登录服务和注册public static void main(String[] args) {new QQView().menu();}private void menu(){while (loop){System.out.println("==========欢迎登录网络通信系统======");System.out.println("\t\t 1 登录系统");System.out.println("\t\t 9 退出系统");//读取用户输入Scanner scanner = new Scanner(System.in);System.out.println("请选择你的操作:");String key = scanner.next();switch (key){case "1"://读取用户输入Scanner scanner2 = new Scanner(System.in);System.out.println("请输入用户名");String name = scanner2.next();System.out.println("请输入密码:");String password = scanner2.next();//服务器端去验证用户信息是否合法if(userClientService.checkUser(name,password)){System.out.println("==========欢迎"+name+"登陆成功======");//进入二级菜单while (loop){System.out.println("==========网络通信系统二级菜单(用户"+name+")======");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 退出登录");//读取用户输入Scanner scanner1 = new Scanner(System.in);System.out.println("请选择你的操作:");String key1 = scanner1.next();switch (key1){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 "5":loop = false;System.out.println("退出登录");break;}}}else{System.out.println("登录失败。");}break;case "9":loop = false;break;}}}}

package www.study.qqClient.service;import www.study.qqcommon.Message;import www.study.qqcommon.MessageType;import www.study.qqcommon.User;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import .InetAddress;import .Socket;/*** 主要负责用户登录是的信息认证*/public class UserClientService {private User u = new User();private Socket socket;/*public boolean checkUser(String userid, String password) {boolean b = false;//创建user对象u.setPassword(password);u.setUserid(userid);//连接服务器,发送user对象try {socket = new Socket(InetAddress.getLocalHost(), 9999);//得到 ObjectOutputStream对象ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(u);//发送user对象//读取服务器端回复的Message 对象ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());Message ms = (Message) ois.readObject();//强制转换if (ms.getMessagetype().equals(MessageType.MESSAGE_LOGIN_SUCCEED)) {//登录成功b = true;//创建一个和服务器保持通信的线程ClientConnectServerThread clientConnectServerThread = new ClientConnectServerThread(socket);clientConnectServerThread.start();//为了后面客户端的扩展,我们把客户端的线程放到集合里管理ManageClientConnectServerThread manageClientConnectServerThread =new ManageClientConnectServerThread();manageClientConnectServerThread.addClientConnectServerThread(userid,clientConnectServerThread);} else {//登录失败,则不能启动和服务器通信的线程;关闭socketsocket.close();}} catch (Exception e) {e.printStackTrace();}return b;}*///根据userId 和 pwd 到服务器验证该用户是否合法public boolean checkUser(String userId, String pwd) {boolean b = false;//创建User对象u.setUserid(userId);u.setPassword(pwd);try {//连接到服务端,发送u对象socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);//得到ObjectOutputStream对象ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(u);//发送User对象//读取从服务器回复的Message对象ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());Message ms = (Message) ois.readObject();if (ms.getMessagetype().equals(MessageType.MESSAGE_LOGIN_SUCCEED)) {//登录OK//创建一个和服务器端保持通信的线程-> 创建一个类 ClientConnectServerThreadClientConnectServerThread clientConnectServerThread =new ClientConnectServerThread(socket);//启动客户端的线程clientConnectServerThread.start();//这里为了后面客户端的扩展,我们将线程放入到集合管理ManageClientConnectServerThread.addClientConnectServerThread(userId, clientConnectServerThread);b = true;} else {//如果登录失败, 我们就不能启动和服务器通信的线程, 关闭socketsocket.close();}} catch (Exception e) {e.printStackTrace();}return b;}}

ClientConnectServerThread

package www.study.qqClient.service;import www.study.qqcommon.Message;import java.io.ObjectInputStream;import .Socket;/*** 创建线程*/public class ClientConnectServerThread extends Thread{//该线程需要持有socketprivate Socket socket;//构造器可以接收一个socket对象public ClientConnectServerThread(Socket socket){this.socket = socket;}@Overridepublic void run(){//因为Thread需要从后台和服务器端通信while (true){try {//得到回复的 Message对象ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());//如果服务器没有发送Message线程会阻塞在这里,线程会一直等待从socket读取数据Message ms = (Message) ois.readObject();//强制转换} catch (Exception e) {e.printStackTrace();}}}}

ManageClientConnectServerThread

package www.study.qqClient.service;import java.util.HashMap;public class ManageClientConnectServerThread {//我们把多个线程放入到一个hashmap中public static HashMap<String,ClientConnectServerThread> hm = new HashMap<>();//添加线程public static void addClientConnectServerThread(String userid,ClientConnectServerThread clientConnectServerThread){hm.put(userid,clientConnectServerThread);}//通过userid得到对应线程public static ClientConnectServerThread getClientConnectServerThread(String userid){return hm.get(userid);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。