当前位置: 首页 > news >正文

Java简易聊天工具(网络通信)

项目结构:分为客户端和服务端,客户端与服务端使用Socket建立连接,服务端接收客户端发来的信息然后转发至目标客户。

一、服务端

1.自定义服务端

package chatroom.server;import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;//自定义服务端
public class MServer {public static void main(String[] args) {try{new MServer().createServer();} catch (Exception e) {throw new RuntimeException(e);}}public void createServer()throws Exception{//创建服务器ServerSocket server=new ServerSocket(8899);System.out.println("启动服务器");//保存所有上线好友Map<User, Socket> map=new HashMap<>();//默认注册好友ArrayList<User> userList=new ArrayList<>();for(int i=1;i<=5;i++){userList.add(new User(i+"0",i+"0"));}while(true){//阻塞监听连接过来的客户端Socket socket=server.accept();//启动线程,保存跟客户端通信ServerThread st=new ServerThread(socket,map,userList);new Thread(st).start();}}
}

2、服务类(使用IO读写数据等功能)

package chatroom.server;import java.io.*;
import java.net.Socket;public class Server {private Socket socket;private OutputStream os;private InputStream is;private BufferedReader br;private BufferedWriter bw;public ObjectOutputStream oos;public Server(Socket socket){this.socket=socket;try {is=socket.getInputStream();os=socket.getOutputStream();br=new BufferedReader(new InputStreamReader(is));bw=new BufferedWriter(new OutputStreamWriter(os));//对象流oos=new ObjectOutputStream(os);} catch (IOException e) {throw new RuntimeException(e);}}//读取数据public String readMsg()throws Exception{String line= br.readLine();return line;}//写入数据public void sendMsg(String msg){try{bw.write(msg);bw.newLine();bw.flush();} catch (IOException e) {throw new RuntimeException(e);}}public void sendMsg(String msg,BufferedWriter bw){try{bw.write(msg);bw.newLine();bw.flush();} catch (IOException e) {throw new RuntimeException(e);}}public void sendObj(Object obj){try {oos.writeObject(obj);oos.flush();} catch (IOException e) {throw new RuntimeException(e);}}public void sendByte(int b){try {os.write(b);os.flush();} catch (IOException e) {throw new RuntimeException(e);}}public void sendByte(int b,OutputStream os){try {os.write(b);os.flush();} catch (IOException e) {throw new RuntimeException(e);}}public int readByte(){int b=0;try {b=is.read();} catch (IOException e) {throw new RuntimeException(e);}return b;}
}

3、用户类

package chatroom.server;import java.io.Serializable;
import java.rmi.server.UID;
//用户类
//获取用户名、密码
//设置用户名、密码
public class User implements Serializable {private String username;private String password;private String chatMsg;//保存每个用户的聊天记录private static final long serialVersionUID=1L;public User(String username,String password) {this.username = username;this.password=password;}public User(){}public String getUsername() {return username;}//获取用户名public String getPassword() {return password;}//获取密码public void setUsername(String username) {this.username = username;}public void setPassword(String password) {this.password = password;}public String getChatMsg() {return chatMsg;}public void setChatMsg(String chatMsg) {this.chatMsg = chatMsg;}
}

4、接口

package chatroom.server;public interface MsgType {//登录public static final byte LOGIN=1;//注册public static final byte REGISTER=2;public static final byte SUCCESS=3;public static final byte ERROR=4;public static final byte DUPLICATE_LOGIN=5;public static final byte DUPLICATE_REGISTER=6;public static final byte MESSAGE=7;
}

5、服务端线程(保存与客户端通信)

package chatroom.server;import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Map;//保存跟客户端通信的线程
public class ServerThread implements Runnable,MsgType {private Socket socket;private Server server;private Map<User,Socket> map;//上线好友private ArrayList<User> userList;//注册好友private User user;public ServerThread(Socket socket, Map<User,Socket> map, ArrayList<User> userList){this.socket=socket;this.map=map;this.userList=userList;server=new Server(socket);}@Overridepublic void run() {while(true){int head=0;try{head=server.readByte();} catch (Exception e) {System.out.println("客户端下线...");//移除用户break;}try{String msg=server.readMsg();System.out.println("msg:"+msg);//消息内容:消息头:消息内容String[] msgArr=msg.split(":");switch (head){case LOGIN:handleLogin(msgArr[0],msgArr[1]);break;case REGISTER:handleRegister(msgArr[0],msgArr[1]);break;case MESSAGE:handleMessage(msgArr[0],msgArr[1]);break;}} catch (Exception e) {throw new RuntimeException(e);}}}//验证登录,重复登录private void handleLogin(String username,String password){System.out.println(username+" login  "+password);//验证是否重复登录for(Map.Entry<User,Socket> entry: map.entrySet()){User u=entry.getKey();if(u.getUsername().equals(username)){server.sendByte(DUPLICATE_LOGIN);return;}}for(User user:userList){System.out.println(user.getUsername()+" login  "+user.getPassword());if(user.getUsername().equals(username)&&user.getPassword().equals(password)){server.sendByte(SUCCESS);try {server.oos.writeObject(userList);} catch (Exception e) {throw new RuntimeException(e);}//添加上线好友map.put(user,socket);this.user=user;break;}}server.sendByte(ERROR);}
//    注册,重复注册private void handleRegister(String username,String password){//验证是否重复注册
//        for(Map.Entry<User,Socket> entry: map.entrySet()){
//            User us=entry.getKey();
//            if(us.getUsername().equals(username)){
//                server.sendMsg(DUPLICATE_REGISTER);
//                return;
//            }
//        }
//        for(User user:userList){//遍历注册好友列表
//            if(user.getUsername().equals(username)){//用户名存在
//                server.sendByte(DUPLICATE_REGISTER);//重复注册
//
//                try {
//                    server.oos.writeObject(new User("1","1"));
//                    server.oos.flush();
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            }
//            //添加上线好友
//            userList.add(user);
//            break;
//        }
//        server.sendByte(ERROR);}//处理聊天消息private void handleMessage(String chatUser,String chatMsg){System.out.println(chatUser+"server"+chatMsg);Socket chatSocket=null;//聊天对象Socket//把消息转发给接收用户//检查聊天对象(chatUser)是否上线//离线消息处理for(Map.Entry<User,Socket> entry:map.entrySet()){User user=entry.getKey();if(chatUser.equals(user.getUsername())){chatSocket=entry.getValue();break;}}//根据在线对象找到对应的Socketif(chatSocket!=null){try {OutputStream os=chatSocket.getOutputStream();BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os));//把消息转发给聊天对象//发送者+聊天内容server.sendByte(MESSAGE,os);server.sendMsg(user.getUsername()+":"+chatMsg,bw);System.out.println("转发消息成功..."+user.getUsername()+":"+chatMsg);} catch (IOException e) {throw new RuntimeException(e);}}}
}

二、客户端

1、自定义客户端

package chatroom.client;import java.io.*;
import java.net.Socket;//自定义客户端
public class MClient {private Socket socket;private OutputStream os;private InputStream is;private BufferedReader br;private BufferedWriter bw;public ObjectInputStream ois;public MClient(){try{socket=new Socket("127.0.0.1",8899);os=socket.getOutputStream();is=socket.getInputStream();br=new BufferedReader(new InputStreamReader(is));bw=new BufferedWriter(new OutputStreamWriter(os));ois=new ObjectInputStream(is);} catch (Exception e) {throw new RuntimeException(e);}}//读取数据public String readMsg(){String line="";try{line=br.readLine();} catch (Exception e) {throw new RuntimeException(e);}return line;}//写入数据public void sendMsg(String msg){try{bw.write(msg);bw.newLine();bw.flush();} catch (IOException e) {throw new RuntimeException(e);}}//读取对象public Object readObject(){Object obj=null;try{obj=ois.readObject();} catch (Exception e) {throw new RuntimeException(e);}return obj;}public void sendByte(int b){try {os.write(b);os.flush();} catch (IOException e) {throw new RuntimeException(e);}}public int readByte(){int b=0;try {b=is.read();} catch (IOException e) {throw new RuntimeException(e);}return b;}
}

2、用户管理类(登录注册功能)

package chatroom.client;import chatroom.server.User;import javax.swing.*;
import java.io.IOException;
import java.util.ArrayList;//用户管理类:登录注册功能
public class UserManage implements MsgType{private MClient mClient;private ArrayList<User> userList;public UserManage(MClient mClient){this.mClient=mClient;}//获取好友名字数据public String[] getUserName(){String[] usernameArr=new String[userList.size()];for(int i=0;i< userList.size();i++){usernameArr[i]=userList.get(i).getUsername();}return usernameArr;}//获取聊天好友public User selectUser(int index) {User u=userList.get(index);return u;}//登录public boolean login(String username,String password){//发送账号密码mClient.sendByte(LOGIN);mClient.sendMsg(username+":"+password);//读取服务端结果int response=mClient.readByte();System.out.println(response);if(SUCCESS==response){//读取好友列表try {userList=(ArrayList<User>) mClient.ois.readObject();} catch (IOException e) {throw new RuntimeException(e);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}return true;} else if (DUPLICATE_LOGIN==response) {JOptionPane .showMessageDialog(null,"账号已登录");return false;}JOptionPane.showMessageDialog(null,"账号或密码错误");return false;}
//    注册
//    public boolean register(String username,String password){
//        User u=new User(username,password);//新用户
//        //设置新用户的用户名和密码
//        u.setPassword(password);
//        u.setUsername(username);
//        //发送账号密码
//        mClient.sendMsg(REGISTER+":"+username+":"+password);
//        //读取客户端结果
//        int response=mClient.readByte();
//        if(SUCCESS==response){
//            try {
//                User user=(User) mClient.ois.readObject();
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            } catch (ClassNotFoundException e) {
//                throw new RuntimeException(e);
//            }
//            return true;
//        } else if (DUPLICATE_REGISTER==response) {
//            JOptionPane .showMessageDialog(null,"账号已注册");
//            return false;
//        }
//        JOptionPane.showMessageDialog(null,"账号或密码不符合规定");
//        return false;
//    }
}

3、接口

package chatroom.client;public interface MsgType {//登录public static final byte LOGIN=1;//注册public static final byte REGISTER=2;public static final byte SUCCESS=3;public static final byte ERROR=4;public static final byte DUPLICATE_LOGIN=5;public static final byte DUPLICATE_REGISTER=6;public static final byte MESSAGE=7;
}

4、客户端线程

package chatroom.client;import javax.swing.*;public class ClientThread implements Runnable,MsgType{private MClient mClient;private String msg;private JTextArea jta;public ClientThread(MClient mClient,JTextArea jta){this.mClient=mClient;this.jta=jta;}public String getMsg(){return msg;}@Overridepublic void run() {while(true){System.out.println("等待服务端发来信息...");int head= mClient.readByte();System.out.println("head:"+head);switch (head){case MESSAGE :msg=mClient.readMsg();String[] msgArr=msg.split(":");System.out.println("server:"+msgArr[0]+" "+msgArr[1]);jta.setText(jta.getText()+msgArr[1]);break;}}}
}

5、登陆界面(在用户登录后启动聊天界面)

package chatroom.client;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class LoginUI {public static void main(String[] args) {MClient mClient=new MClient();UserManage userManage=new UserManage(mClient);new LoginUI(userManage,mClient).showUI();}private UserManage userManage;private MClient mClient;public LoginUI(UserManage userManage,MClient mClient){this.mClient=mClient;this.userManage=userManage;}public void showUI(){//窗体JFrame jf=new JFrame();jf.setSize(450,550);jf.setTitle("登录界面");jf.setLocationRelativeTo(null);//设置居中jf.setDefaultCloseOperation(3);//退出进程//流式布局管理器FlowLayout flow=new FlowLayout();jf.setLayout(flow);//提示信息JLabel user=new JLabel("账号:");jf.add(user);//账号框JTextField usernameFeild=new JTextField();Dimension dm=new Dimension(370,30);usernameFeild.setPreferredSize(dm);jf.add(usernameFeild);JLabel pass=new JLabel("密码:");jf.add(pass);//密码框JTextField passwordFeild=new JTextField();passwordFeild.setPreferredSize(dm);jf.add(passwordFeild);//按钮JButton loginBtn=new JButton("登录");jf.add(loginBtn);JButton registerBtn=new JButton("注册");jf.add(registerBtn);//        匿名内部类//注册
//        registerBtn.addActionListener(new ActionListener() {
//            @Override
//            public void actionPerformed(ActionEvent e) {
//                //获取账号 密码 发送给服务器验证
//                String username=usernameFeild.getText();
//                String password=passwordFeild.getText();
//
//                if(userManage.register(username,password)){
//                    System.out.println("注册成功并登录");
//
//                    new chatUI(username,userManage,mClient);
//                }else{
//                    System.out.println("注册失败");
//                }
//            }
//        });//登录loginBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//获取账号 密码 发送给服务器验证String username=usernameFeild.getText();String password=passwordFeild.getText();if(userManage.login(username,password)){System.out.println("登录成功");chatUI ui=new chatUI(username,userManage,mClient);ui.usernameJlist.setListData(userManage.getUserName());}else{System.out.println("登录失败");}}});//设置可见jf.setVisible(true);}
}

6、聊天界面

package chatroom.client;import chatroom.server.User;import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class chatUI implements MsgType{public JList<String> usernameJlist;private UserManage userManage;private MClient mClient;private ClientThread ct;private JTextArea jta;public chatUI(String username,UserManage userManage,MClient mClient){this.userManage=userManage;this.mClient=mClient;initUI(username);//启动线程读取数据ct=new ClientThread(mClient,jta);new Thread(ct).start();}public void initUI(String username){JFrame jf=new JFrame(username);jf.setSize(580,600);jf.setLocationRelativeTo(null);jf.setDefaultCloseOperation(3);//JPanel 默认流式布局JPanel centerPanel=new JPanel();centerPanel.setBackground(Color.WHITE);jf.add(centerPanel,BorderLayout.CENTER);//显示消息jta=new JTextArea();jta.setPreferredSize(new Dimension(450,480));jta.setEditable(false);centerPanel.add(jta);//消息发送框JTextField jtf=new JTextField();jtf.setPreferredSize(new Dimension(400,40));centerPanel.add(jtf);JButton sendBtn=new JButton("发送");centerPanel.add(sendBtn);//好友列表面板JPanel westPanel=new JPanel();westPanel.setBackground(Color.white);westPanel.setSize(new Dimension(80,0));jf.add(westPanel,BorderLayout.WEST);//显示好友数据usernameJlist=new JList<>();usernameJlist.setFont(new Font("楷体",0,20));westPanel.add(usernameJlist,BorderLayout.CENTER);jf.setVisible(true);usernameJlist.addListSelectionListener(new ListSelectionListener() {@Overridepublic void valueChanged(ListSelectionEvent e) {
//                jta.setText(user.getChatMsg());}});sendBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//确定选择好友int index=usernameJlist.getSelectedIndex();User user=userManage.selectUser(index);//聊天对象String chatName=user.getUsername();String chatMsg=jtf.getText();//聊天内容mClient.sendByte(MESSAGE);mClient.sendMsg(chatName+":"+chatMsg);}});}
}


http://www.mrgr.cn/news/2902.html

相关文章:

  • Linux下使用cat、grep、sed查看文件任意几行的数据
  • 大公报发表欧科云链署名文章:发行港元稳定币,建Web3.0新生态
  • IOS 12 自定义用户协议对话框
  • 多线程锁机制面试
  • Linux 离线安装docker和docker-compose
  • 领英(LinkedIn)公司主页创建方法分享
  • 【微信小程序】WXS脚本
  • 提取代理IP为何有最小提取间隔?如何获取自身业务有效时间代理?
  • 有哪些同声传译软件?精选5款实用工具
  • 矩阵中的最大得分(Lc3148)——动态规划
  • python-docx在word文件表格中指定行下插入新一行并填充值
  • HTML—css
  • 深度deepin v23系统也能玩《黑神话:悟空》 8GB内存、GTX 1660 Ti丝滑流畅
  • 永久旋转 PDF 文件的 3 种简便方法
  • ip归属地换地方了会自动更新吗
  • Python批量导入一亿条数据进Oracle数据库
  • nginx的详细介绍及配置
  • Coze的卡片制作和使用
  • 计算机Java项目|基于SpringBoot的实习管理系统的设计与实现
  • 通讯专题-RS232