java实现网络聊天

 网络聊天实现步骤(从功能谈论方法):

客户端:

1.登录面板:注册提醒用户注册格式,登录账号密码不为空,点击登录的时候需要连接服务器端,启动聊天面板。(监听用户点击登录,这时候连接服务器)

2.聊天面板:消息框接收服务器端发送的消息,发送消息框保存消息内容,点击发送按钮将发送消息框递给服务器端(需要创造一个线程不断监听服务器端发送回来的消息,并且显示在消息框)

服务器端:

1.服务器端需要循环监听客户端发送过来的连接

2.把循环接收到的多个客户端用集合储存起来

3.为每个客户端建立一个线程,用来接收他们发送的消息并且为其他客户端转送消息。

4.发送公告功能:聊天面板,发送公告面板,发送按钮(将发送面板的消息发送给各个客户端)。

客户端启动界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.Socket;public class Logon extends JFrame {public Logon() {this.setTitle("欢迎登录");this.setSize(400, 400);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//标签JLabel jLabel = new JLabel("欢迎登录");jLabel.setFont(new Font("楷体", Font.BOLD, 20));//字体jLabel.setForeground(new Color(21, 12, 12));JPanel jPanel = new JPanel();jPanel.add(jLabel);//账号JPanel jPanel1 = new JPanel();JLabel jLabel1 = new JLabel("账号");JTextField jTextField1 = new JTextField(15);jPanel1.add(jLabel1);jPanel1.add(jTextField1);//密码JPanel jPanel2 = new JPanel();JLabel jLabel2 = new JLabel("密码");JTextField jTextField2 = new JTextField(15);jPanel2.add(jLabel2);jPanel2.add(jTextField2);//按钮//登录JButton jButton = new JButton("登录");jButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if (jTextField1.getText().equals("") || jTextField2.getText().equals("")) {JOptionPane.showMessageDialog(null, "请输入");} else {try {Socket socket = new Socket("192.168.124.89", 9999);new ChatMap(jTextField1.getText(),socket);dispose();} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null, "没有连接至服务器,请稍后");}}}});//注册JButton jButton1 = new JButton("注册");jButton1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if (!jTextField1.getText().matches("\\w*") || !jTextField2.getText().matches("\\w*")) {JOptionPane.showMessageDialog(null, "只支持大小写字母及数字");}}});JPanel jPanel3 = new JPanel();jPanel3.add(jButton);jPanel3.add(jButton1);this.setLayout(new GridLayout(4, 1));this.add(jPanel);this.add(jPanel1);this.add(jPanel2);this.add(jPanel3);this.setVisible(true);//让窗口显示,放在代码的最后一行。}
}

客户端聊天界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;public class ChatMap extends JFrame {JTextArea jTextArea;public ChatMap(String account, Socket socket) throws IOException {//向服务器发送信息DataOutputStream dataOutputStream=new DataOutputStream(socket.getOutputStream());this.setTitle("欢迎来到"+account+"聊天室");this.setSize(400, 400);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//创造面版JPanel jPanel = new JPanel(new BorderLayout());//聊天窗口jTextArea = new JTextArea(20, 15);jTextArea.setEnabled(false);jTextArea.setLineWrap(true);JScrollPane jScrollPane = new JScrollPane(jTextArea);jPanel.add(jScrollPane,BorderLayout.NORTH);//输入窗口JTextArea jTextArea1 = new JTextArea(1, 10);jTextArea.setLineWrap(true);JScrollPane jScrollPane1 = new JScrollPane(jTextArea1);jPanel.add(jScrollPane1,BorderLayout.CENTER);//按钮JButton jButton=new JButton("发送");jButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String message=jTextArea1.getText();if(message.length()==0)//为什么要依靠message长度判断{JOptionPane.showMessageDialog(null, "输入不能为空");return;}//不为空显示日期向服务器发送信息Date date=new Date();SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String str=sdf.format(date);String msg=account+":"+str+"\n";msg+=message;try {dataOutputStream.writeUTF(msg);//发送消息jTextArea1.setText("");//清空发送框} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null, "内容发送失败,请检查网络");}}});jPanel.add(jButton,BorderLayout.EAST);this.add(jPanel);this.setVisible(true);//让窗口显示,放在代码的最后一行。//面板创造完毕建立监听(服务器传入的消息)new BThread(socket,jTextArea).start();}//内部类监听服务器端class BThread extends Thread{DataInputStream dataInputStream;public BThread(Socket socket,JTextArea jTextArea) throws IOException {dataInputStream=new DataInputStream(socket.getInputStream());}@Overridepublic void run() {while(true)//循环条件:退出{try {String message=dataInputStream.readUTF();jTextArea.append(message+"\n");} catch (IOException e) {e.printStackTrace();System.out.println("服务器断开连接");break;//停止客户端线程}}}}}

 

启动客户端
public class Run {public static void main(String[] args) {new Logon();}
}
服务器端界面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;public class server extends JFrame {ArrayList<Socket> sockets=new ArrayList<>();Socket socket;JTextArea jTextArea;JTextArea  jTextArea1;JButton jButton;public server(){//设置窗口this.setTitle("服务器");this.setSize(400, 400);this.setLocationRelativeTo(null);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);JPanel jPanel=new JPanel(new BorderLayout());jTextArea=new JTextArea();jTextArea.setEnabled(false);//不可进行操作jTextArea.setLineWrap(true);JScrollPane jScrollPane=new JScrollPane(jTextArea);//发送JPanel jPanel1=new JPanel();jTextArea1=new JTextArea();jTextArea1.setEnabled(true);//可进行操作jTextArea1.setLineWrap(true);JScrollPane jScrollPane1=new JScrollPane(jTextArea1);jButton=new JButton("发送");jButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String massage=jTextArea1.getText();for (Socket s:sockets){DataOutputStream dOut= null;try {dOut = new DataOutputStream(s.getOutputStream());dOut.writeUTF("公告:"+massage);} catch (IOException ioException) {ioException.printStackTrace();JOptionPane.showMessageDialog(null, "发送失败");}}}});jPanel1.add(jScrollPane1);jPanel1.add(jButton);jPanel.add(jScrollPane);jPanel.add(jPanel1,BorderLayout.SOUTH);this.add(jPanel);this.setVisible(true);//启动服务器this.startServer();}public void startServer(){try {ServerSocket serverSocket=new ServerSocket(9999);while(true){socket= serverSocket.accept();//阻塞程序System.out.println("服务器启动成功");sockets.add(socket);System.out.println("有客户端连接上了,客户端连接数为:"+sockets.size());//为每一个连接到服务器的客户端开启一个线程new A(socket).start();}} catch (IOException e) {e.printStackTrace();System.out.println("启动服务器失败");}}//创造一个内部类监听各个客户端是否给服务器端发送消息class A extends Thread{DataInputStream dataInputStream;public A(Socket socket) throws IOException {dataInputStream=new DataInputStream(socket.getInputStream());}@Overridepublic void run() {while (true){//一直厮混换,监听客户端发送的消息try {String msg=dataInputStream.readUTF();jTextArea.append(msg+"\n");//向不同的客户端转发消息for(Socket s:sockets){DataOutputStream dOut=new DataOutputStream(s.getOutputStream());dOut.writeUTF(msg);}} catch (IOException e) {e.printStackTrace();System.out.println("一位客户端下线了");sockets.remove(socket);break;}}}}
}

 

启动服务器
public class serverRun {public static void main(String[] args) {new server();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/264438.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL - InnoDB 和 MyISAM 的索引实现的区别

InnoDB 和 MyISAM 底层都是 B 树的实现&#xff0c;但是二者却完全不同 。 主键索引文件存储不同 MyISAM 引擎的索引文件和数据文件是分离的&#xff0c;而 InnoDB 引擎的索引文件和数据文件是不分离的。 MyISAM 引擎的叶子节点存储的是数据文件的地址&#xff0c;而 InnoDB 的…

unity 2d 入门 飞翔小鸟 死亡闪烁特效(十三)

一、c#脚本 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Bling : MonoBehaviour {public Texture img;public float speed;public static bool changeWhite false;private float alpha0f;// Start is called before the fi…

【STM32】关于H743中出现的ANA类型引脚

最近调试H743ZI这个封装的H743的LAN8720功能 LAN8720是需要用一个外部引脚进行外部复位的 之前也没有好好看手册&#xff0c;选了PC2_C来做这个输出低电平复位信号的IO口 但是重点来了&#xff0c;PC2_C其实它不能做普通IO口&#xff0c;无法控制其输出高低电电平)!!! 手册上写…

nodejs微信小程序+python+PHP在线学习平台设计与实现-计算机毕业设计推荐

概念模型是对现实中的问题出现的事物的进行描述&#xff0c;ER图是由实体及其关系构成的图&#xff0c;通过E-R图可以清楚地描述系统涉及到的实体之间的相互关系。 困扰管理层的许多问题当中,在线学习也是不敢忽视的一块。但是管理好在线学习又面临很多麻烦需要解决,例如&…

流水号的获取

软件中&#xff0c;常常使用流水号&#xff0c;通常流水号是一组参数的组合&#xff0c;如&#xff1a;评估报告的编号结构&#xff1a; 区编号-机构类型-年份-性别-流水 如&#xff1a;03-01-2023-W-0001 03-01-2023-M-0002 03-01-2023-M-0003 。。。。。。 编程时&#xff0c…

有病但合理的 ChatGPT 提示语

ChatGPT 面世一年多了&#xff0c;如何让大模型输出高质量内容&#xff0c;让提示词工程成了一门重要的学科。以下是一些有病但合理的提示词技巧&#xff0c;大部分经过论文证明&#xff0c;有效提高 ChatGPT 输出质量&#xff1a; ​1️⃣ Take a deep breath. 深呼吸 ✨ 作用…

Threejs发光闪烁提示特效

一、导语 发光闪烁特效应该在我们的项目中是经常需要去封装的一个特效吧&#xff0c;一般用于点击选择&#xff0c;选中物体&#xff0c;或者一些特效加持于中心物体&#xff0c;物体碰撞检测后的发光特效等等 二、分析 我们可以合理的使用后处理特效&#xff0c;上步骤&am…

【git】关于git二三事

文章目录 前言一、创建版本库1.通过命令 git init 把这个目录变成git可以管理的仓库2.将修改的内容添加到版本库2.1 git add .2.2 git commit -m "Xxxx"2.3 git status 2.4 git diff readme.txt3.版本回退3.1 git log3.2 git reset --hard HEAD^ 二、理解工作区与暂存…

【unity实战】一个通用的FPS枪支不同武器射击控制脚本

文章目录 前言模型素材文章用到的粒子火光特效射击效果换弹瞄准开枪抖动效果设置显示文本最终代码不同武器射击效果1. 手枪2. 机枪3. 狙击枪4. 霰弹枪5. 加特林 其他感谢完结 前言 实现FPS枪支不同武器效果&#xff0c;比如手枪&#xff0c;喷子&#xff0c;狙击枪&#xff0c…

ffmpeg6.0之ffprobe.c源码分析二-核心功能源码分析

本篇我们继续分析: 1、ffprobe -show_packets 参数的处理流程;2、ffprobe -show_frames 参数的处理流程;3、ffprobe -show_streams 参数的处理流程;4、ffprobe -show_format 参数的处理流程; 因为前面的文章已经回顾了这些命令的使用,以及作用。本文就不在赘述,以免篇幅…

TeeChart.NET 2023.11.17 Crack

.NET 的 TeeChart 图表控件提供了一个出色的通用组件套件&#xff0c;可满足无数的图表需求&#xff0c;也针对重要的垂直领域&#xff0c;例如金融、科学和统计领域。 数据可视化 数十种完全可定制的交互式图表类型、地图和仪表指示器&#xff0c;以及完整的功能集&#xff0c…

【rabbitMQ】rabbitMQ用户,虚拟机地址(添加,修改,删除操作)

rabbitMQ的下载&#xff0c;安装和配置 https://blog.csdn.net/m0_67930426/article/details/134892759?spm1001.2014.3001.5502 rabbitMQ控制台模拟收发消息 https://blog.csdn.net/m0_67930426/article/details/134904365?spm1001.2014.3001.5502 目录 用户 添加用户…