Java基础知识,JavaSwing,Java多线程,JavaTCP网络编程 写两个线程,一个实现接收客户端发送的消息功能,并采用消息队列的方式存储消息;一个实现群发消息队列中消息的功能。服务器启动时,使用while(true)不断尝试与客户端建立连接,每当建立一个连接后,将该连接保存到一个队列中,为群发消息时,找到发送对象做准备。 同样写两个线程,一个实现不断接收服务器发回来的消息,一个实现在按下发送消息后,将消息发送出去。 采用继承Thread类的方式,循环与客户端建立连接,并以一个内部类的方式来接收消息,每当建立一个连接,便将该连接加入到连接对列,这里采用Set,并且启动一个内部类线程开始接收该连接的消息,接收到的消息加入消息队列,然后将消息队列及连接队列同步到发送消息线程,并启动发送消息线程,发送一次消息 通过构造器来初始化消息队列及连接队列,若消息队列中存在未发送的消息,则取连接队列中的每个连接,依次发送消息给每个客户端,实现群聊天 该窗体中保存有用户设置的端口号,并且以该端口号创建一个ServerSocket对象,并且通过接收线程类的构造器将这个对象传给接收消息线程,在创建该窗体的同时启动接收消息线程。 窗体效果如下图 启动服务器时,首先显示该窗体,用以设置连接服务器的端口号,该窗体有三个组件,关闭程序的按钮,设置端口的按钮,以及填写要设置的端口号的文本框,当设置号端口号后,使该窗体销毁,并且启动主窗体 该窗体效果如下图 一个简单的main方法 到此服务器就完成了,接下来开始写客户端 该窗体用于输入需要连接的服务器的端口号,以及在群聊中以什么昵称发送消息。 该窗体效果如下图 以两个内部类的形式来实现接收消息和发送消息线程,发送消息线程以while(true)不断接收来自服务器的消息并将其显示在历史消息处,而发送消息线程,每次启动会将此时消息框内的文本发送出去。窗体创建时,开启接收消息线程,每当按下发送消息按钮后,启动一次接收消息线程。 该窗体效果如下图 到此该项目就写完了,每次启动时先起服务器后起客户端,客户端可起多个。 最后附上源代码及可执行jar包 学习阶段主要以实现功能为主,界面不够美观以及代码不够完善的地方请多包涵。
Java实现简单群聊天
所用技术
思路
服务器
客户端
服务器
接收消息线程
import java.io.DataInputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.HashSet; import java.util.LinkedList; /** * 接收消息,线程 */ public class ReceiveNews extends Thread{ //保存消息 private LinkedList<String> queue = new LinkedList(); //服务器Socket private ServerSocket server; //客户端Socket private Socket socket; //保存Socket HashSet<Socket> socketSet = new HashSet<>(); public ReceiveNews(ServerSocket server) { this.server = server; } @Override public void run(){ while(true){ //接收连接 try { socket = server.accept(); socketSet.add(socket); //为该连接开启接收消息线程 new Receive(socket).start(); } catch (IOException e) { e.printStackTrace(); } } } class Receive extends Thread { //接收消息 private DataInputStream in; //Socket对象 private Socket socket; public Receive(Socket socket){ this.socket = socket; try { in = new DataInputStream(socket.getInputStream()); } catch (IOException e) { e.printStackTrace(); } } @Override public void run(){ while(true){ String temp = ""; try { temp = in.readUTF(); } catch (IOException e) { e.printStackTrace(); } //加入消息队列 queue.add(temp); //将队列同步到发送消息线程 new SendNews(queue,socketSet).start(); } } } }
发送消息线程
import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.util.HashSet; import java.util.LinkedList; /** * 发送消息线程 */ public class SendNews extends Thread{ //保存消息 private LinkedList<String> queue = new LinkedList(); //发送消息 private DataOutputStream writer; //客户端Socket private HashSet<Socket> socketSet; public SendNews(LinkedList<String> queue,HashSet<Socket> socketSet){ this.queue = queue; this.socketSet = socketSet; } @Override public void run(){ //如果有消息未发 if(queue.size() > 0){ //获取队列中的消息 String message = queue.pollFirst();; //给每个客户端发送消息 for(Socket socket : socketSet){ try { writer = new DataOutputStream(socket.getOutputStream()); //发送消息 System.out.println("发送消息"); writer.writeUTF(message); writer.flush(); } catch (IOException e) { e.printStackTrace(); } } } } }
主窗体
import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.ServerSocket; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import talking.thread.ReceiveNews; /** * 服务器窗体 */ public class MainFrame extends JFrame implements ActionListener{ //关闭服务器按钮 private JButton exit = new JButton("关闭服务器"); //保存端口号 private int post; //显示端口号 private JLabel show; //接收消息线程 private ReceiveNews receive; //服务器Socket private ServerSocket server; public MainFrame(int post) { //初始化 this.post = post; try { server = new ServerSocket(post); } catch (IOException e) { e.printStackTrace(); } show = new JLabel("服务器已启动端口号:" + post); init(); //接收消息线程启动 receive = new ReceiveNews(server); receive.start(); } private void init(){ //设置窗口名称 this.setTitle("服务器"); //窗口大小固定 this.setResizable(false); //设置窗口关闭 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置字体 exit.setFont(new Font("宋体",1,18)); show.setFont(new Font("宋体",1,18)); //添加监听 exit.addActionListener(this); //设置布局 this.setLayout(null); this.setBounds(700,300,300,500); exit.setBounds(70,300,150,30); show.setBounds(20,150,300,90); //添加组件 this.add(exit); this.add(show); //窗体可见 this.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { JButton button = (JButton) e.getSource(); if(button.equals(exit)){//退出 System.exit(0); } } }
设置端口窗体
import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTextField; /** * 设置端口号窗体 */ public class SetPost extends JFrame implements ActionListener{ private static final long serialVersionUID = 1L; //确定按钮 private JButton set = new JButton("设置端口号"); //关闭窗口按钮 private JButton exit = new JButton("关闭"); //窗口输入 private JTextField write = new JTextField(); //端口号 private JLabel post = new JLabel("端口号"); public SetPost() { //初始化 init(); } private void init(){ //设置窗口名称 this.setTitle("服务器"); //窗口大小固定 this.setResizable(false); //设置窗口关闭 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置字体 exit.setFont(new Font("宋体",1,18)); set.setFont(new Font("宋体",1,18)); write.setFont(new Font("宋体",1,18)); post.setFont(new Font("宋体",1,18)); //添加监听 exit.addActionListener(this); set.addActionListener(this); //设置布局 this.setLayout(null); this.setBounds(600,300,400,280); set.setBounds(50,150,150,30); exit.setBounds(250,150,80,30); write.setBounds(100,80,200,20); post.setBounds(30,80,150,20); //添加组件 this.add(exit); this.add(set); this.add(write); this.add(post); //窗体可见 this.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { JButton button = (JButton) e.getSource(); if(button.equals(exit)){//退出 System.exit(0); }else if(button.equals(set)){//确认 String message = write.getText(); int post; try{ post = Integer.parseInt(message); }catch(NumberFormatException exception){ JOptionPane.showMessageDialog(null, "请输入整数"); write.setText(""); return; } this.dispose(); new MainFrame(post); } } }
启动服务器的类
import talking.frame.SetPost; /** * 服务器启动 */ public class Start { public static void main(String[] args) { //创建服务器窗体 new SetPost(); } }
客户端
选择端口号及连接服务器名称窗体
import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTextField; /** * 设置端口号窗体 */ public class SetPost extends JFrame implements ActionListener{ private static final long serialVersionUID = 1L; //确定按钮 private JButton set = new JButton("进入"); //关闭窗口按钮 private JButton exit = new JButton("关闭"); //窗口输入 private JTextField write = new JTextField(); private JTextField name = new JTextField(); //显示端口,姓名 private JLabel showPost = new JLabel("端口号"); private JLabel showName = new JLabel("姓 名"); public SetPost() { //初始化 init(); } private void init(){ //设置窗口名称 this.setTitle("客户端"); //窗口大小固定 this.setResizable(false); //设置窗口关闭 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置字体 exit.setFont(new Font("宋体",1,18)); set.setFont(new Font("宋体",1,18)); write.setFont(new Font("宋体",1,18)); name.setFont(new Font("宋体",1,18)); showPost.setFont(new Font("宋体",1,18)); showName.setFont(new Font("宋体",1,18)); //添加监听 exit.addActionListener(this); set.addActionListener(this); //设置布局 this.setLayout(null); this.setBounds(700,300,400,280); set.setBounds(70,150,80,30); exit.setBounds(230,150,80,30); write.setBounds(90,50,200,25); name.setBounds(90,100,200,25); showPost.setBounds(30,47,150,30); showName.setBounds(36,97,120,30); //添加组件 this.add(exit); this.add(set); this.add(write); this.add(name); this.add(showName); this.add(showPost); //窗体可见 this.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { JButton button = (JButton) e.getSource(); if(button.equals(exit)){//退出 System.exit(0); }else if(button.equals(set)){//确认 String message = write.getText(); int post; try{ post = Integer.parseInt(message); }catch(NumberFormatException exception){ JOptionPane.showMessageDialog(null, "请输入整数"); write.setText(""); return; } if("".equals(name.getText())){ JOptionPane.showMessageDialog(null, "名称不能为空"); return; } this.dispose(); new MainFrame(post,name.getText()); } } }
主窗体
import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.ServerSocket; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import talking.thread.ReceiveNews; /** * 服务器窗体 */ public class MainFrame extends JFrame implements ActionListener{ //关闭服务器按钮 private JButton exit = new JButton("关闭服务器"); //保存端口号 private int post; //显示端口号 private JLabel show; //接收消息线程 private ReceiveNews receive; //服务器Socket private ServerSocket server; public MainFrame(int post) { //初始化 this.post = post; try { server = new ServerSocket(post); } catch (IOException e) { e.printStackTrace(); } show = new JLabel("服务器已启动端口号:" + post); init(); //接收消息线程启动 receive = new ReceiveNews(server); receive.start(); } private void init(){ //设置窗口名称 this.setTitle("服务器"); //窗口大小固定 this.setResizable(false); //设置窗口关闭 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置字体 exit.setFont(new Font("宋体",1,18)); show.setFont(new Font("宋体",1,18)); //添加监听 exit.addActionListener(this); //设置布局 this.setLayout(null); this.setBounds(700,300,300,500); exit.setBounds(70,300,150,30); show.setBounds(20,150,300,90); //添加组件 this.add(exit); this.add(show); //窗体可见 this.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { JButton button = (JButton) e.getSource(); if(button.equals(exit)){//退出 System.exit(0); } } }
上为历史消息框,下为消息框。
启动客户端的类
import talking.frame.SetPost; /** * 服务器启动 */ public class Start { public static void main(String[] args) { //创建服务器窗体 new SetPost(); } }
链接:小聊天室
提取码:jbk0
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算