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

用java编写一个网络聊天室

网络聊天室

服务器:

1.启动服务器,在服务器端循环监听客户端的连接

try {ServerSocket serverSocket=new ServerSocket(6622);System.out.println("服务器已启动");while(true){//把客户端实例添加到sockets里Socket socket=serverSocket.accept();sockets.add(socket);System.out.println("当前连接到客户端数量:"+sockets.size());//为每一个链接过来的客户端开一个线程new SocketThread(socket).start();}} catch (IOException e) {e.printStackTrace();System.out.println("服务器创建失败");}

2.把循环接收到的多个客户端Socket对象存储起来(集合)

ArrayList<Socket> sockets=new ArrayList<>();

3.在服务器端每个Socket都要监听各自客户端发来的消息

while(true){try {String msg=dataInputStream.readUTF();jTextAreamsg.append(msg+"\n");//在服务器端显示msg}} catch (IOException e) {e.printStackTrace();System.out.println("客户端下线了");}}

4.一旦某个客户端发送了消息,那么在服务器端,就将此消息转发给其他的客户

//向不同客户端转发消息//遍历socketsfor (Socket socket:sockets){//客户端1 客户端2 客户端3DataOutputStream dataOutputStream=new DataOutputStream(socket.getOutputStream());dataOutputStream.writeUTF(msg);}
客户端:

1.用户登录,创建Socket

 Socket socket = new Socket("xxxxxxxxx", 6622);

2.如果Socket创建成功,打开聊天窗口

new ChatWindow(jTextaccount.getText(), socket);//打开聊天窗口

3.输入内容,点击发送按钮发送消息

4.在客户端监听服务器发送回来的消息,并把消息显示出来

class ClientThread extends Thread{DataInputStream dataInputStream;public ClientThread(Socket socket) throws IOException {dataInputStream=new DataInputStream(socket.getInputStream());}@Overridepublic void run() {while(true){try {String msg=dataInputStream.readUTF();jTextArea.append(msg+"\n");//可以显示聊天内容并且保持原先内容} catch (IOException e) {e.printStackTrace();break;}}}}

完整代码:

ChatWindow:

public class ChatWindow extends JFrame {JTextArea jTextArea;public ChatWindow(String name, Socket socket) throws IOException {DataOutputStream dos=new DataOutputStream(socket.getOutputStream());this.setTitle("欢迎"+name+"登录");this.setSize(500,500);this.setLocationRelativeTo(null);//居中this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//关闭窗口时退出程序this.setResizable(false);//禁止窗口拖拽//创建面板JPanel jPanel=new JPanel();jTextArea=new JTextArea(22,43);//显示文本域jTextArea.setEditable(false);//不可修改的JTextArea jTextArea2=new JTextArea(5,33);//发送文本域jTextArea2.setLineWrap(true);//强制换行JScrollPane j=new JScrollPane(jTextArea2);//滚动条JButton jButtonsend=new JButton("发送");jPanel.add(jTextArea);jPanel.add(j);jPanel.add(jButtonsend);this.add(jPanel);this.setVisible(true);//来到聊天窗口jButtonsend.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String message=jTextArea2.getText();if(message.length()==0){//输入为空JOptionPane.showMessageDialog(null,"发送内容不能为空");return;}else{//不为空,向服务器发送消息String msg=name+"  "+new SimpleDateFormat("HH:mm:ss").format(new Date());msg=msg+"\n"+message;try {dos.writeUTF(msg);//发送成功清空发送内容jTextArea2.setText("");} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null,"内容发送失败,请检查网络连接");}}}});new ClientThread(socket).start();this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {int res=JOptionPane.showConfirmDialog(null,"你确定要退出聊天吗?","警告",JOptionPane.OK_CANCEL_OPTION);if(res==0){//点击确定new LoginWindow();dispose();}}});}//监听服务器发的消息(即客户端123的消息)class ClientThread extends Thread{DataInputStream dataInputStream;public ClientThread(Socket socket) throws IOException {dataInputStream=new DataInputStream(socket.getInputStream());}@Overridepublic void run() {while(true){try {String msg=dataInputStream.readUTF();jTextArea.append(msg+"\n");//可以显示聊天内容并且保持原先内容} catch (IOException e) {e.printStackTrace();break;}}}}}

LoginWindow:

public class LoginWindow extends JFrame {public LoginWindow(){this.setTitle("欢迎登录");this.setSize(500,350);this.setLocationRelativeTo(null);//居中this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭窗口时退出程序this.setResizable(false);//禁止窗口拖拽JPanel jPanel=new JPanel();JLabel jLabel=new JLabel("欢迎登录");jLabel.setFont(new Font("横体", Font.BOLD,30));jPanel.add(jLabel);//欢迎登录//中间第一个空标签JLabel jLabel1=new JLabel();//欢迎登录下面空白部分jLabel1.setPreferredSize(new Dimension(500,50));//账号JLabel jLabelAccount=new JLabel("账号");//账号标签jLabelAccount.setPreferredSize(new Dimension(30,30));JTextField jTextaccount=new JTextField(15);//账号文本域//中间第二个空标签JLabel jLabel2=new JLabel();//欢迎登录下面空白部分jLabel2.setPreferredSize(new Dimension(500,20));//密码JLabel jLabelPassword=new JLabel("密码 ");//账号标签jLabelPassword.setPreferredSize(new Dimension(30,30));JPasswordField jPasswordField=new JPasswordField(15);//中间第二个空标签JLabel jLabel3=new JLabel();//欢迎登录下面空白部分jLabel3.setPreferredSize(new Dimension(500,20));//按钮JButton ButtonLogin=new JButton("登录");JButton ButtonSign=new JButton("注册");jPanel.add(jLabel1);jPanel.add(jLabelAccount);jPanel.add(jTextaccount);jPanel.add(jLabel2);jPanel.add(jLabelPassword);jPanel.add(jPasswordField);jPanel.add(jLabel3);jPanel.add(ButtonLogin);jPanel.add(ButtonSign);this.add(jPanel);this.setVisible(true);//按钮事件ButtonLogin.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if(jTextaccount.getText().equals("")||jPasswordField.getText().equals("")){//当账号或密码为空时,弹出警告JOptionPane.showMessageDialog(null,"账号和密码不能为空","警告",JOptionPane.ERROR_MESSAGE);return;}else if(!((jTextaccount.getText().matches("\\w{1,100}"))&&(jPasswordField.getText().matches("\\w{1,100}")))){//当1-100范围内不是字母和数字时弹出警告JOptionPane.showMessageDialog(null,"账号密码只能由数字,字母组成","警告",JOptionPane.ERROR_MESSAGE);return;}//创建Socketelse {try {Socket socket = new Socket("10.13.0.67", 6622);new ChatWindow(jTextaccount.getText(), socket);//打开聊天窗口dispose();//释放窗口} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null, "服务器连接失败,请稍后再试");}}}});}
}

Run:

public class Run {public static void main(String[] args) {new LoginWindow();}
}

Server:

public class Server extends JFrame {JTextArea jTextAreamsg;//放到成员变量便于在内部类中也可以使用//客户端连接的数量ArrayList<Socket> sockets=new ArrayList<>();public void ServerStart(){this.setTitle("我是服务器");this.setSize(500,500);this.setLocationRelativeTo(null);//居中this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//关闭窗口时退出程序this.setResizable(false);//禁止窗口拖拽JPanel jPanel=new JPanel();jTextAreamsg=new JTextArea(28,43);jTextAreamsg.setLineWrap(true);//强制换行JScrollPane jScrollPane=new JScrollPane();jTextAreamsg.setEditable(false);//不可修改的jPanel.add(jTextAreamsg);jPanel.add(jScrollPane);this.add(jPanel);this.setVisible(true);//关闭窗口this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {int res=JOptionPane.showConfirmDialog(null,"你确定要关闭服务器吗?","警告",JOptionPane.OK_CANCEL_OPTION);if(res==0){//点击确定dispose();}}});try {ServerSocket serverSocket=new ServerSocket(6622);System.out.println("服务器已启动");while(true){//把客户端实例添加到sockets里Socket socket=serverSocket.accept();sockets.add(socket);System.out.println("当前连接到客户端数量:"+sockets.size());//为每一个链接过来的客户端开一个线程new SocketThread(socket).start();}} catch (IOException e) {e.printStackTrace();System.out.println("服务器创建失败");}}//内部类,用来监听自己客户端有没有发消息class SocketThread extends Thread{Socket socket;//用来引入到run方法DataInputStream dataInputStream;public SocketThread(Socket socket) throws IOException {this.socket=socket;//把成员变量socket赋值为传入的socket参数,以便于客户端下线后可以从sockets里移除客户端dataInputStream=new DataInputStream(socket.getInputStream());}@Overridepublic void run() {//循环监听客户端自己发送消息while(true){try {String msg=dataInputStream.readUTF();jTextAreamsg.append(msg+"\n");//在服务器端显示msg//向不同客户端转发消息//遍历socketsfor (Socket socket:sockets){//客户端1 客户端2 客户端3DataOutputStream dataOutputStream=new DataOutputStream(socket.getOutputStream());dataOutputStream.writeUTF(msg);}} catch (IOException e) {e.printStackTrace();System.out.println("客户端下线了");sockets.remove(socket);break;}}}}
}

ServerRun:

public class ServerRun {public static void main(String[] args) {new Server().ServerStart();}
}

在这个过程中监听服务器消息和监听客户端消息都用到了内部类,这样的好处是可以之间在内部类中使用大类里面的jTextArea和sockets

http://www.lryc.cn/news/248061.html

相关文章:

  • Opencv颜色追踪
  • 计算机网络——网络可靠性及网络出口配置
  • 在虚拟机搭建nignx,和使用本地访问nginx的情况
  • Java数据结构之《直接插入排序》问题
  • 向量场中的几个恒等式
  • 异行星低代码平台--第三方插件对接:钉钉平台对接(一)
  • MyBatis使用教程详解<下>
  • C++基础 -17-继承中 基类与派生构造和析构调用顺序
  • uniapp实现表单弹窗
  • Ajax 是什么? 如何创建一个 Ajax?
  • 【LeetCode】101. 对称二叉树
  • O-Star|再相识
  • 最新PHP熊猫头图片表情斗图生成源码
  • 子虔科技出席2023WAIC“智能制造融合创新论坛”
  • 递归算法学习——二叉树的伪回文路径
  • Android端极致画质体验之HDR播放
  • 【Java SE】带你在String类世界中遨游!!!
  • Android: ListView + ArrayAdapter 简单应用
  • 前端:实现二级菜单(点击实现二级菜单展开)
  • Spark-java版
  • RabbitMQ消息模型之Work Queues
  • vue3+ts 实现时间间隔选择器
  • PTA 魔法优惠券
  • P8A110-A120经典赛题
  • 文件基础知识
  • 二叉树OJ题之二
  • MySql表中添加emoji表情
  • 【新手解答1】深入探索 C 语言:变量名、形参 + 主调函数、被调函数 + 类和对象 + 源文件(.c 文件)、头文件(.h 文件)+ 库
  • 2023最新的软件测试热点面试题(答案+解析)
  • NCo3.1(08) - Nco3 服务器端编程