利用Java网络通信技术实现一个迷你聊天室
说明:此聊天室由四个类构成,ChatRoomServer.java,是聊天室的服务器,要是一直开启状态,然后是客户端方面的LinkServerFrame.java,Client.java和ClientFrame.java。
可以打开多个客户端,只要连接在同一个局域网就可以互相聊天啦!下面是代码和运行截图:
1.首先是服务器类 ChatRoomServer.java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
public class ChatRoomServer {
private HashSet<Socket> allSockets;//客户端套接字集合
private ServerSocket serverSocket;//服务器套接字
public ChatRoomServer(){
try {
serverSocket = new ServerSocket(4545);
} catch (IOException e) {
e.printStackTrace();
}
allSockets = new HashSet<Socket>();
}
public void startServer() throws IOException{
while(true){
Socket socket = serverSocket.accept();//获得一个客户端连接
System.out.println("用户已经进入聊天室");
allSockets.add(socket);//将客户端连接的套接字放到集合中
ServerThread t = new ServerThread(socket);
t.start();
}
}
private class ServerThread extends Thread{
Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try {
String str = br.readLine();
if(str.contains("EXIT")){//%EXIT:用户名%
String tmp = str.split(":")[1]+"用户退出聊天室";
sendMessageToAllClient(tmp);
allSockets.remove(socket);
socket.close();
return;
}
sendMessageToAllClient(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void sendMessageToAllClient(String str){
for(Socket s:allSockets){
try {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write(str);
bw.newLine();
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args){
try {
ChatRoomServer s = new ChatRoomServer();
s.startServer();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务器端大功告成开始搭建客户端!
2.连接服务器的界面类:LinkServerFrame.java
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.JobAttributes;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.*;
public class LinkServerFrame extends JFrame{//连接服务器的窗体
public JTextField textFieid1;//接收服务器IP地址的文本框
public JTextField textFieid2;//接受用户名的文本框
public JButton button;//连接服务器
public JLabel label1;//服务器IP地址
public JLabel label2;//用户名
public LinkServerFrame() {
textFieid1 = new JTextField();
textFieid2 = new JTextField();
button = new JButton("连接服务器");
label1 = new JLabel(" 服 务 器 I P 地 址:");
label2 = new JLabel(" 用 户 名:");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(!textFieid1.getText().equals("")&&!textFieid2.getText().equals("")){
//文本框内容不为空
dispose();//销毁当前窗体
//创建客户端窗体并传参
try {
ClientFrame clientFrame = new ClientFrame(textFieid1.getText().trim(), textFieid2.getText().trim());
clientFrame.setVisible(true);
} catch (IOException e1) {
e1.printStackTrace();
}
}else{
JOptionPane.showMessageDialog(null,"文本框的内容不能为空!","警告",JOptionPane.WARNING_MESSAGE);
}
}
});
JPanel north = new JPanel(new GridLayout(2,2,10,10));
JPanel south = new JPanel(new FlowLayout());
north.add(label1);
north.add(textFieid1);
north.add(label2);
north.add(textFieid2);
south.add(button);
setTitle("连接服务器");
setVisible(true);
setBounds(200, 200, 400, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();//获取容器
c.setLayout(new GridLayout(2,1,10,10));//网格布局,两行一列
c.add(north);//添加面板
c.add(south);
}
public static void main(String[] args) {
new LinkServerFrame();
}
}
3.然后是客户端类:Client.java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class Client {
private Socket socket;
private BufferedWriter bw;
private BufferedReader br;
public Client(String ip,int port) throws IOException{
socket = new Socket(ip,port);
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
public void sendMessage(String message) throws IOException{
bw.write(message);
bw.newLine();
bw.flush();
}
public String reciveMessage() throws IOException{
String message = null;
message = br.readLine();
return message;
}
public void close(){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.最后客户端界面类ClientFrame .java
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;
public class ClientFrame extends JFrame{
private JPanel contentPane;//中间面板
private JPanel southPane;//底部面板
private JLabel lblUserName;//显示用户名
private JTextField tfMessage;//信息发送文本
private JButton btnSend;//发送按钮
private JTextArea textArea;//信息接收文本域
private String userName;//用户名称
Client client;//客户端连接对象
private void init(){
setTitle("聊天室");
setResizable(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(200,200,450,300);
lblUserName = new JLabel(userName);//初始化各个标签
tfMessage = new JTextField(25);
btnSend = new JButton("发送");
textArea = new JTextArea(50,40);
contentPane = new JPanel();//中间面板
contentPane.add(textArea);
southPane = new JPanel(new FlowLayout());//底部面板浮动排版
southPane.add(lblUserName,new FlowLayout().LEFT);
southPane.add(tfMessage);
southPane.add(btnSend, new FlowLayout().RIGHT);
Container c = getContentPane();//获取容器
c.add(contentPane,new BorderLayout().CENTER);//将面板添加到容器中
c.add(southPane,new BorderLayout().SOUTH);
}
public ClientFrame(String ip,String userNmae) throws IOException {
this.userName = userNmae;
init();//添加窗体初始化内容
addListener();//添加监听事件
client = new Client(ip,4545);//创建客户端对象
ReadMessageThread t = new ReadMessageThread();
t.start();
}
private class ReadMessageThread extends Thread{
@Override
public void run() {
while(true){
try {
String str = client.reciveMessage();
textArea.append(str+"\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void addListener() {
btnSend.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
try {
client.sendMessage(userName+" "+df.format(date)+":\n "+tfMessage.getText());
tfMessage.setText("");//清空输入框
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
this.addWindowListener(new WindowAdapter() {//开启窗口监听事件
public void windowClosing(WindowEvent e){
int op = JOptionPane.showConfirmDialog(ClientFrame.this,"确定退出聊天室么?","确定",JOptionPane.YES_NO_OPTION);
if(op == JOptionPane.YES_OPTION){//如果选择是
try {
client.sendMessage("%EXIT%:"+userName);//发送消息
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} catch (IOException e1) {
e1.printStackTrace();
}
client.close();//关闭客户端线程
System.exit(0);
}
}
});
}
}
先启动服务器,然后再启动客户端,输入服务器的IP地址就可以啦!这个小程序可以和舍友之间(连接同一个电脑开的wifi就行)聊天,迷你QQ,你值得拥有