效果:
?客户端:
package com.ngd.chatRoom;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ChatClient extends JFrame {
Socket socket;
PrintWriter pWriter;
BufferedReader bReader;
JPanel panel;
JScrollPane sPane;
JTextArea txtContent;
JLabel lblName,lblSend;
JTextField txtName,txtSend;
JButton btnSend;
public ChatClient(){
super("聊天室");
txtContent = new JTextArea();
//设置文本域只读
txtContent.setEditable(false);
sPane = new JScrollPane(txtContent);
lblName = new JLabel("昵称:");
txtName = new JTextField(5);
lblSend = new JLabel("发言:");
txtSend = new JTextField(20);
btnSend = new JButton("发送");
panel = new JPanel();
panel.add(lblName);
panel.add(txtName);
panel.add(lblSend);
panel.add(txtSend);
panel.add(btnSend);
this.add(panel, BorderLayout.SOUTH);
this.add(sPane);
this.setSize(500,300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
//创建一个套接字
socket = new Socket("127.0.0.1",9999);
//创建一个往套接字中写数据的管道,即输出流,给服务器发送信息
pWriter = new PrintWriter(socket.getOutputStream());
//创建一个套接字读取数据的管道,即输入流,读服务器的返回信息
bReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//注册监听
btnSend.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//获取用户输入的文本
String strName = txtName.getText();
String strMsg = txtSend.getText();
if (!strMsg.equals("")){
//通过输出流将数据发送给服务器
pWriter.println(strName+"说:"+strMsg);
pWriter.flush();
//清空文本框
txtSend.setText("");
}
}
});
//启动线程
new GetMsgFromServer().start();
}
class GetMsgFromServer extends Thread{
@Override
public void run() {
while (this.isAlive()){
try {
String strMsg = bReader.readLine();
if (strMsg != null){
//在文本域中显示聊天信息
txtContent.append(strMsg+"\n");
}
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
//创建聊天室客户端窗口实例,并显示
new ChatClient().setVisible(true);
}
}
服务器:
package com.ngd.chatRoom;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
//聊天室服务器端
public class ChatServer {
//声明服务器端套接字ServerSocket
ServerSocket serverSocket;
//输入流列表集合
ArrayList<BufferedReader> bReaders = new ArrayList<BufferedReader>();
//输出流列表集合
ArrayList<PrintWriter> pWriters = new ArrayList<PrintWriter>();
//聊天信息链表集合
LinkedList<String> msgList = new LinkedList<String>();
public ChatServer(){
try {
//创建服务器端套接字ServerSocket,在9999端口监听
serverSocket = new ServerSocket(9999);
} catch (IOException e) {
e.printStackTrace();
}
//创建接收客户端Socket的线程实例,并启动
new AcceptSocketThread().start();
//创建给客户端发送信息的线程实例,并启动
new SendMsgToClient().start();
System.out.println("服务器已启动...");
}
//接收客户端Socket套接字线程
class AcceptSocketThread extends Thread{
@Override
public void run() {
while (this.isAlive()){
try {
//接收一个客户端Socket对象
Socket socket = serverSocket.accept();
//建立该客户端的通信管道
if (socket != null){
//获取Socket对象的输入流
BufferedReader bReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//将输入流添加到输入列表集合中
bReaders.add(bReader);
//开启一个线程接收该客户端的聊天信息
new GetMsgFromClient(bReader).start();
//获取Socket对象的输出流,并添加到输出流列表集合中
pWriters.add(new PrintWriter(socket.getOutputStream()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//接收客户端的聊天信息的线程
class GetMsgFromClient extends Thread{
BufferedReader bReader;
public GetMsgFromClient(BufferedReader bReader){
this.bReader = bReader;
}
@Override
public void run() {
while (this.isAlive()){
try {
//从输入流中读一行信息
String strMsg = bReader.readLine();
if (strMsg != null){
//SimpleDateFormat日期格式化类,指定日期格式为“年-月-日 时:分:秒”
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
//获取当前系统时间,并使用日期格式化类格式化指定格式的字符串
String strTime = dateFormat.format(new Date());
//将时间和信息添加到信息链表集合中
msgList.addFirst("<=="+strTime+"==>\n"+strMsg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//给所有客户发送聊天信息的线程
class SendMsgToClient extends Thread{
@Override
public void run() {
while (this.isAlive()){
try {
//如果信息链表集合不空(还有聊天信息未发送)
if (!msgList.isEmpty()){
//获取链表信息的最后一条,并移除
String msg = msgList.removeLast();
//对输出流列表集合进行遍历,循环发送信息给所有客户端
for (int i = 0; i<pWriters.size();i++){
pWriters.get(i).println(msg);
pWriters.get(i).flush();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new ChatServer();
}
}
|