2021-04-04

这个Java程序实现了一个简单的多人聊天室,基于Socket通信。存在代码组织混乱、异常处理不完善以及服务器端管理功能不足的问题。优化点包括重构代码以提高可读性,确保客户端和服务器的正常关闭流程,以及增强服务器对客户端的管理能力。
摘要由CSDN通过智能技术生成

简单的java聊天室(基于java socket)

该聊天室实现多个用户间聊天通信的问题。

ChatSocket

public class ChatSocket implements Runnable{
    private Socket socket = null;
    private DataInputStream inputStream = null;
    private DataOutputStream outputStream = null;
    
    public DataInputStream getInputStream() {
        return inputStream;
    }

    public DataOutputStream getOutputStream() {
        return outputStream;
    }
   public ChatSocket(Socket socket) {
        this.socket = socket;
        try {
            inputStream = new DataInputStream(socket.getInputStream());
            outputStream = new DataOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


    public void send(String send) { //向客户端发送数据
        try {
            outputStream.writeUTF(send);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() { //循环读取客户端发来的数据
        String accept = null;

        while (true) {
            try {
                accept = inputStream.readUTF();
                ClientMannager.sendAll(this, accept);
            } catch (IOException e) {
                ClientMannager.sockets.remove(this);
            }
        }
    }
}

ClientMannager

import java.util.Vector;//动态数组Vector,它对数据传输帮助很大

//用户端管理器
public class ClientMannager {

    private ClientMannager() {//对ClientMannager构造方法,且为私有
    }

    public static Vector<ChatSocket> sockets = new Vector<>();

    public static void sendAll(ChatSocket chatSocket, String send) {
        for (ChatSocket socket : sockets) {
            if (!chatSocket.equals(socket)) {//朝其他用户发送数据
                socket.send(send);
            }
        }
    }
}

ClientView

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.*;

@SuppressWarnings("serial")
public class ClientView extends JFrame implements ActionListener, KeyListener, Runnable {
    private JTextArea textArea;//文本域
    private JTextField textField, tfName;//输入框
    private JButton btnSend, btnId;//选择按钮
    private JLabel label;//标签
    private JPanel jp1, jp2;//容器
    public boolean isConnect = false;//是否连接标志
    private Socket socket = null;
    private DataInputStream inputStream = null;
    private DataOutputStream outputStream = null;
    //private DataInputStream flistI = null;
    //private DataOutputStream flistO = null;
    private JScrollPane scrollPane;//滚动条
    private static ClientView view;
    private JTextArea friend;

    public JTextArea getTextArea() {//获取文本域
        return textArea;
    }

    public DataInputStream getInputStream() {//读取数据
        return inputStream;
    }
    public DataOutputStream getOutputStream() {//输出数据
        return outputStream;
    }

    public static void main(String[] args) {//主函数启动程序
        view = new ClientView();//启动客户端界面
        ServiceView.clientViews.add(view);//客户端加载到服务器中
        Thread thread = new Thread(view);//开启多个服务器
        thread.start();
    }

    public ClientView() {
        initView();
        try {
            socket = new Socket("localhost", 9090);//连接本地服务器

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initView() {//客户端页面布局
        textArea = new JTextArea(20, 20);//文本域
        textArea.setEditable(false);
        friend=new JTextArea(10,20);
        scrollPane = new JScrollPane(textArea);//加入滚动条
        textField = new JTextField(15);//输入框
        textField.addKeyListener(this);//监听输入框
        btnSend = new JButton("发送");//发送按钮
        btnSend.addActionListener(this);//监听发送按钮
        label = new JLabel("账号:");
        tfName = new JTextField(8);
        jp1 = new JPanel();
        jp2 = new JPanel();
        jp1.add(label); 
        jp1.add(tfName);
        //tfName.setText("用户0");
        jp1.setLayout(new FlowLayout(FlowLayout.CENTER));//本人信息
        jp2.add(textField);
        jp2.add(btnSend);
        jp2.setLayout(new FlowLayout(FlowLayout.CENTER));//发送信息

        add(jp1, BorderLayout.NORTH);//顶部展示本人
        add(friend,BorderLayout.EAST);
        add(scrollPane, BorderLayout.CENTER);//中部展示聊天内容
        add(jp2, BorderLayout.SOUTH);//底部展示发送信息
        setTitle("聊天室");
        setSize(500, 500);
        setLocation(450, 150);
        setVisible(true);     //画出界面
        setDefaultCloseOperation(EXIT_ON_CLOSE);//关闭聊天框
        addWindowListener(new WindowAdapter() { //窗口关闭后断开连接
            @Override
            public void windowClosing(WindowEvent e) {
                try {
                    if (socket != null)
                        socket.close();      //关闭三个连接
                    if (inputStream!= null)
                        inputStream.close(); //关闭三个连接
                    if (outputStream != null)
                        outputStream.close();//关闭三个连接
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        });
    }

    public void actionPerformed(ActionEvent e) {//点击按钮发送信息
        if (e.getSource() == btnSend) {
            sendMsg();
        }
    }

    private void sendMsg() {
        try {
            String s = textField.getText();
            if (!s.equals("")) {           //发送数据
                textField.setText("");     //按一定格式组成我的显示信息
                textArea.append("我(" + tfName.getText() +  "):\r\n" + s + "\r\n");
                outputStream = new DataOutputStream(socket.getOutputStream());
                outputStream.writeUTF(tfName.getText() + "#" + s);//从管道中读取数据 
                outputStream.flush();//清除缓冲
                
                //flistO = new DataOutputStream(socket.getOutputStream());
               // flistO.writeUTF(tfName.getText() + "#" + s);//从管道中读取数据 
                //outputStream.flush();//清除缓冲
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }



    public void keyPressed1(KeyEvent arg0) {//通过换行键发送信息
        if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
            sendMsg();
        }
    }

   
    public void keyTyped(KeyEvent arg0) {

    }

    @Override
    public void run() {//显示他人传入的信息
        try {
            inputStream = new DataInputStream(socket.getInputStream());
            while (true) {
                String[] s = inputStream.readUTF().split("#");
                textArea.append(s[0] + ":\r\n" + s[1] + "\r\n");
                friend.append(s[0]+"\n");
            }
        } catch (IOException e) {
        }

    }

	//public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	//}

	///@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	//@Override
	//public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		
	//}
}

Service

public class Service implements Runnable{
//ClientMannager a=new ClientMannager();
    private ServerSocket serverSocket = null;//服务器端

    public ServerSocket getServerSocket() {
        return serverSocket;
    }

    @Override
    public void run() {
        try {
            serverSocket = new ServerSocket(9090); //创建端口
            while (true) { //循地接收客户端的连接
                Socket socket = serverSocket.accept();
                JOptionPane.showMessageDialog(ServiceView.getView(), "客户端连接端口", "TIP", JOptionPane.INFORMATION_MESSAGE);//消息提示器
                ChatSocket chatSocket = new ChatSocket(socket); //新客户端连接
                ClientMannager.sockets.add(chatSocket); //往客户端管理器里添加客户
                Thread thread = new Thread(chatSocket); 
                thread.start();

            }
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("服务器关闭");
        }
    }

}

ServiceView

public class ServiceView extends JFrame implements ActionListener{
    private JButton btnOpen, btnStop;//打开,关闭按钮
    private JLabel label;
    private Service service = null;
    public static ArrayList<ClientView> clientViews = new ArrayList<>();
    private static ServiceView view;

    public static ServiceView getView() {
        return view;
    }
    public static void main(String[] args) {
        view = new ServiceView();//从view开始调动整个程序
    }

    public ServiceView() {//构造函数
        initView();
    }

    private void initView() {
        btnOpen = new JButton("打开服务器");
        btnStop = new JButton("关闭服务器");
        btnStop.setEnabled(false);
        btnOpen.addActionListener(this);
        btnStop.addActionListener(this);
        label = new JLabel("服务器停止工作");
        add(label);
        add(btnOpen);
        add(btnStop);
        setTitle("服务器");
        setLayout(new GridLayout(3, 1, 0, 10));
        setSize(300, 300);
        setLocation(450, 150);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(btnOpen) ) {
            open();
        } 
        else {
            stop();
        }
    }


    public void open() { //开启服务器
        service = new Service();
        Thread thread = new Thread(service);
        thread.start();
        label.setText("服务器正在运行");
        btnOpen.setEnabled(false);
        btnStop.setEnabled(true);
    }

    public void stop() { //关闭服务器
        label.setText("服务器已关闭");
        btnOpen.setEnabled(true);
        btnStop.setEnabled(false);
        try {
            synchronized (ClientMannager.sockets) { //关闭各个连接
                for (ChatSocket socket : ClientMannager.sockets) {
                    socket.getInputStream().close();
                    socket.getOutputStream().close();
                }
                ClientMannager.sockets.removeAllElements();
            }


            for (ClientView view : clientViews) {
                view.getInputStream().close();
                view.getOutputStream().close();
            }

            service.getServerSocket().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
	//@Override
	//public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		
	//}

}

待完善的问题

1.代码写得条理不清晰,各个块的功能较混乱。应将功能打包,规范化。关键是要多加注释!!!
2.若是先关闭服务器端或先开启客户端都会出现bug,这里不够完善;
3.服务器端未能实现对客户端的强大管理功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值