Java简单聊天室

时间:2023-02-26 00:27:49

实现Java简单的聊天室

  所用主要知识:多线程+网络编程

    效果如下图

Java简单聊天室

/**
*
* @author Administrator
*
* 简单的多人聊天系统——重点:同时性,异步性
* 1、客户端:发送消息,并且接收消息
* 1.1 消息发送至服务器:服务器每次都将客户发过来的信息发送到每个客户端
* 1.2 接收消息:发送的同时也要接收消息,所以必须有两个线程,一个发送消息,一个接收消息
* 1.3 关于这两个线程:如果没有线程,接收和发送就是按顺序执行的了,那么是发送后接收还是接收后发送?或者是
* 一边可以发送一边又可以接收呢?答案不言而喻
* 1.4 在客户端,用可以通过界面的点击按钮事件发送消息,所以就要开启一个线程来接收服务器发送给客户端的消息了
* 1.5 多线程:不需按步骤逐步循环,可以和其他程序同时执行,不相互干扰
* 2、服务器端:接收所有用户的消息并且借每个用户的消息发送给连接了服务器的客户端
* 2.1 服务器既要接收C端信息又要想所有C端发送信息,先收后发。一收就发。
* 2.2 S端还要显示C端上线提醒
* 2.3 上线提醒和收发信息是不影响的,互不干扰的,但是都要在S端上执行,如果没有线程,所以的程序都要按顺序执行了所以又要 多线程
* 2.4 一个线程负责向所以C端发送接收到的任何一条信息,一个线程负责显示C端上线的信息
*
* 3、类:S端:Server、ServerFrame、sendThread 三个类
* C端:Client、ClientFrame 两个类
*
*/

 package com.java.chat;

 import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List; import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea; public class Server {
//用于保存Socket的集合,也可以说是把个C端与S端的一个连接通道保存起来
//作用:服务器将接收到的信息发给集合里的所以socket,也就是发给每个C端
public static List<Socket> list = new ArrayList<Socket>(); public static void main(String[] args) {
new ServerFrame("服务器端");
} } /*
* 继承Jframe类表示该类可以创建一个窗口程序了,
* 实现ActionListener:动作监听,在S端点击“启动服务器”是要执行的代码
* 实现Runnable:实现多线程,该窗口是个客户端窗口,要开启一个线程接收显示服务器发过来的信息
*/
class ServerFrame extends JFrame implements ActionListener, Runnable { private static final long serialVersionUID = 1L; private ServerSocket serverSocket = null; private Socket socket; private JButton start;
private JTextArea message; public ServerFrame(String name) {
super(name); start = new JButton("启动服务器");
start.addActionListener(this);
message = new JTextArea();
message.setEditable(false);
this.add(start, "North");
this.add(message, "Center"); this.setResizable(false);
this.setBounds(0, 0, 400, 300);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} @Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == start) {
// 如果点击的按钮是开始按钮。则启动服务器。
try {
serverSocket = new ServerSocket(6666);
message.setText("服务器已启动。。。"); //单击“启动服务器”开启一个线程用于获取用户上线的情况
new Thread(this).start(); } catch (IOException e1) {
e1.printStackTrace();
}
}
} //获取C端上线的情况
@Override
public void run() {
String address = null;
int port = 0;
//用一个死循环一直让S端开启接收C端的连接,将C端的IP和端口显示在面板上
//如果用循环的话就只能接收一次
while (true) {
try {
socket = serverSocket.accept();
Server.list.add(socket);
address = socket.getInetAddress().getHostAddress();
port = socket.getPort();
message.append("\r\nip/" + address + ":" + port + "\t上线了"); //开启转发信息的线程
new sendThread(socket).start(); } catch (IOException e) {
// System.out.println(address + ":" + port + "\t退出了服务器");
}
}
} } /*
* 接收每个C端的信息并向每个C端发送接收到的信息
*/
class sendThread extends Thread {
private Socket socket; public sendThread(Socket socket) {
super();
this.socket = socket;
} @Override
public void run() {
InputStream is = null;
BufferedReader br = null;
String str = null;
OutputStream os = null;
BufferedWriter bw = null;
while (true) {
try {
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
str = br.readLine();
for (Socket s : Server.list) {
os = s.getOutputStream();
bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write(str);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
//如果断开连接则移除对于的socket
Server.list.remove(socket);
}
}
}
}

服务器端代码

 package com.java.chat;

 import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date; import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField; /**
*
* @author Administrator
*
*/ public class Client {
public static void main(String[] args) {
new ClientFrame("客户端");
}
} /*
* 继承Jframe类表示该类可以创建一个窗口程序了,
* 实现ActionListener:动作监听,就是一个事件发送后应该执行什么就要重新它的方法
* 实现Runnable:实现多线程,该窗口是个客户端窗口,要开启一个线程接收显示服务器发过来的信息
*/
class ClientFrame extends JFrame implements ActionListener, Runnable { private static final long serialVersionUID = 1L; private Socket socket;
OutputStream os = null;
BufferedWriter bw = null; JTextArea message;
JScrollPane scroll;
JTextField input;
JButton submit;
JPanel panel; String uname = "";
// 聊天页面
JPanel chat; // 登录页面
JPanel login;
JTextField username;
JButton ok; public ClientFrame(String name) {
super(name); message = new JTextArea();
message.setEditable(false);
scroll = new JScrollPane(message);
input = new JTextField(20);
submit = new JButton("发送");
panel = new JPanel(); panel.add(input);
panel.add(submit);
chat = new JPanel(new BorderLayout());
chat.add(scroll, "Center");
chat.add(panel, "South"); // 在创建客户端窗体是就要把客户端与服务端连接
try {
//127.0.0.1表示本机地址,地址好端口都可以改,这要看服务器那边是什么地址和端口
socket = new Socket("127.0.0.1", 6666);
os = socket.getOutputStream();
bw = new BufferedWriter(new OutputStreamWriter(os)); } catch (IOException e1) {
e1.printStackTrace();
} /* 在创建C端窗体的时候也应该开启一个线程接收显示来自服务器的信息
* 为什么要开启一个线程呢?因为在这个窗体里既要实现消息的发送,
* 也要接收信息,而且两个不能按顺序进行,也互不干扰,所以开启一个线程时时刻刻等着S端发来的信息
*/
//接收信息
new Thread(this).start(); //提交按钮工作监听器,点击提交时触发
submit.addActionListener(this); login = new JPanel();
username = new JTextField(20);
ok = new JButton("确定");
ok.addActionListener(this);
JLabel label = new JLabel("请输入用户名");
label.setFont(new Font(Font.DIALOG, Font.BOLD, 28));
label.setForeground(Color.red);
login.add(label);
login.add(username);
login.add(ok); this.add(chat);
this.add(login); this.setResizable(false);
this.setBounds(400, 100, 400, 300);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} @Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == submit) {
// 如果点击提交按钮,则表示需要将信息发送出去。
String str = null;
//以下三行是创建发送时间的代码
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
String dateStr = format.format(date); str = uname+" "+dateStr+" "+input.getText(); try {
bw.write(str);
bw.newLine();
// System.out.println("客户端发送了:"+str);
bw.flush();
} catch (IOException e1) {
System.out.println("无法发送,服务器连接异常!");
} // System.out.println(str); } else if (e.getSource() == ok) {// 用户登录
uname = username.getText();// 获取文本框输入的文本信息
if ("".equals(uname)) {
JOptionPane.showMessageDialog(this, "用户名不能为空!");
} else {
login.setVisible(false);
chat.setVisible(true);
this.setTitle(uname + " 的客户端");
this.add(chat);
}
}
} //run方法里面的是接受S端信息和将信息显示的代码
@Override
public void run() {
BufferedReader br = null;
InputStream is = null;
String str = null;
try {
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
while (true) {
str = br.readLine()+"\r\n";
message.append(str);
}
} catch (IOException e) {
System.out.println("无法发送,服务器连接异常!");
}
} }

客户端代码

(完)

Java简单聊天室的更多相关文章

  1. java web利用mvc结构实现简单聊天室功能

    简单聊天室采用各种内部对象不适用数据库实现. 一个聊天室要实现的基本功能是:         1.用户登录进入聊天室, 2.用户发言 3.用户可以看见别人发言 刚才算是简单的需求分析了,现在就应该是进 ...

  2. Java Socket聊天室编程&lpar;一&rpar;之利用socket实现聊天之消息推送

    这篇文章主要介绍了Java Socket聊天室编程(一)之利用socket实现聊天之消息推送的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 网上已经有很多利用socket实现聊天的例子了 ...

  3. SpringBoot 搭建简单聊天室

    SpringBoot 搭建简单聊天室(queue 点对点) 1.引用 SpringBoot 搭建 WebSocket 链接 https://www.cnblogs.com/yi1036943655/p ...

  4. 基于Server-Sent Event的简单聊天室 Web 2&period;0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。

    基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...

  5. Python Socket 简单聊天室2

    上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  6. Java Socket聊天室编程&lpar;二&rpar;之利用socket实现单聊聊天室

    这篇文章主要介绍了Java Socket聊天室编程(二)之利用socket实现单聊聊天室的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 在上篇文章Java Socket聊天室编程(一)之 ...

  7. Asp&period;Net SignalR - 简单聊天室实现

    简单聊天室 使用持久链接类我们就可以做一些即时通讯的应用了,我使用Group做了一个简单的聊天室,先上图技术细节下面再讲 可以加入聊天室.创建聊天室.发送消息,下面就说说我是如何通过Group做出来的 ...

  8. ASP&period;NET SingalR &plus; MongoDB 实现简单聊天室(一):搭建基本框架

    ASP.NET SingalR不多介绍.让我介绍不如看官网,我这里就是直接上源代码,当然代码还是写的比较简单的,考虑的也少,希望各位技友多多提意见. 先简单介绍聊天室功能: 用户加入聊天室,自动给用户 ...

  9. 利用socket&period;io&plus;nodejs打造简单聊天室

    代码地址如下:http://www.demodashi.com/demo/11579.html 界面展示: 首先展示demo的结果界面,只是简单消息的发送和接收,包括发送文字和发送图片. ws说明: ...

随机推荐

  1. BaaS模式的开发思路

    如今,有一种BaaS服务(后端即服务)的模式,即无需编程即可生成后端应用及相应API. Drupal这套CMS下,有一款插件Services,可以在线直接自定义各种格式如json.xmlrpc.web ...

  2. Mongos与集群均衡

    版权声明:本文由孔德雨原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/190 来源:腾云阁 https://www.qclo ...

  3. Microsoft Robotics Developer Studio 4

    Microsoft Robotics Developer Studio 4       Share   Language: English   Download Microsoft® Robotics ...

  4. phpmyadmin导出数据库为什么是php文件

    你的迅雷在作怪,把它卸载了,或者在迅雷的高级设置中,关闭监听浏览器,就不会触发迅雷下载,就没问题了.或者360浏览器的话,把急速模式改为兼容模式

  5. CareerCup它1&period;8 串移包括问题

    [称号] 原文: 1.8 Assume you have a method isSubstring which checks if one word is a substring of another ...

  6. 基础二 day4 日记

    1.list增删改查 l1 = [1,'alex',True,[1,2,3],(2,3,4),{'name':'alex'}]l1 = ['alex',True,'wusir','ritian','t ...

  7. ORACLE sid&comma;pid&comma;spid总结

    概念上:1.spid (system process id)  是操作系统层面的进程id .2.pid(process id)  这个是基于oracle的进程id个人理解为就是oracle给自己的进程 ...

  8. nodejs分离html文件里面的js和css

    摘要: 本文要实现的内容,使用nodejs 对文件的增删改查,演示的例子->分离出一个html 文件里面的script 和style 里面的内容,然后单独生成js文件和css 文件.中间处理异步 ...

  9. Docker:Dockerfile命令详解

    1.FROM 功能为指定基础镜像,并且必须是第一条指令. 如果不以任何镜像为基础,那么写法为:FROM scratch. 同时意味着接下来所写的指令将作为镜像的第一层开始 语法: FROM <i ...

  10. numpy&period;random&period;uniform()

    numpy.random.uniform均匀分布 2018年06月19日 23:28:03 徐小妹 阅读数:4238   numpy.random.uniform介绍: 1. 函数原型:  numpy ...