网络聊天实现步骤(从功能谈论方法):
客户端:
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() {
@Override
public 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() {
@Override
public 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() {
@Override
public 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());
}
@Override
public 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 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() {
@Override
public 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());
}
@Override
public 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();
}
}