?文章來源地址http://www.zghlxwxcb.cn/news/detail-503109.html
說明:如果一個(gè)?類,需要有界面的顯示,那么該類就需要繼承自JFrame,此時(shí),該類就可以被稱為一個(gè)“窗體類"。
?文章來源:http://www.zghlxwxcb.cn/news/detail-503109.html
服務(wù)端代碼:
package cn.qy.chat;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
//說明:如果一個(gè)類,需要有界面的顯示,那么該類就需要繼承自JFrame,此時(shí),該類就可以被稱為一個(gè)“窗體類"
//1.定義JFrame窗體中的組件
//2.在構(gòu)造方法中初始化組件
//3.使用網(wǎng)絡(luò)編程完成數(shù)據(jù)的傳輸(TCP,UDP協(xié)議)
//4.實(shí)現(xiàn)“發(fā)送”按鈕的監(jiān)聽點(diǎn)擊事件。需要注意的是,文本域拼接數(shù)據(jù)時(shí),需要自己換行,不要在發(fā)送數(shù)據(jù)時(shí)換行。
public class ServerChatMain extends JFrame implements ActionListener, KeyListener {
public static void main(String[] args) {
// 調(diào)用構(gòu)造器
new ServerChatMain();
}
//屬性
//文本域
private JTextArea jta;
//滾動(dòng)條
private JScrollPane jsp;
//面板
private JPanel jp;
//文本框
private JTextField jtf;
//按鈕
private JButton jb;
//流
BufferedReader br;
BufferedWriter bw;
//服務(wù)端端口號(hào)
private static int serverPort;
//靜態(tài)代碼塊加載外部配置文件
//特點(diǎn)1:在類加載時(shí),自動(dòng)執(zhí)行
//特點(diǎn)2:一個(gè)類只會(huì)加載一次,因此靜態(tài)代碼塊只會(huì)執(zhí)行一次
static {
Properties prop = new Properties();
try {
prop.load(new FileReader("chat.properties"));
serverPort =Integer.parseInt(prop.getProperty("serverPort"));
} catch (IOException e) {
e.printStackTrace();
}
}
//創(chuàng)建空參構(gòu)造器
public ServerChatMain(){
//初始化組件
//初始化文本域
jta = new JTextArea();
//設(shè)置文本域不可編輯
jta.setEditable(false);
//將文本域添加到滾動(dòng)條中,實(shí)現(xiàn)滾動(dòng)效果
jsp = new JScrollPane(jta);
//面板
jp = new JPanel();
jtf = new JTextField(15);
jb = new JButton("發(fā)送");
//將文本框與按鈕添加到面板中
jp.add(jtf);
jp.add(jb);
//將滾動(dòng)條與面板全部添加到窗體中
this.add(jsp, BorderLayout.CENTER);
this.add(jp, BorderLayout.SOUTH);
//設(shè)置 標(biāo)題,大小,位置,關(guān)閉,是否可見
this.setTitle("QQ 服務(wù)端");
this.setSize(300,300);
this.setLocation(600,300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗體關(guān)閉,程序退出
this.setVisible(true);
/******************TCP 服務(wù)端 start*****************/
//給發(fā)送按鈕綁定一個(gè)監(jiān)聽點(diǎn)擊事件
jb.addActionListener(this);
//給文本框綁定一個(gè)鍵盤點(diǎn)擊事件
jtf.addKeyListener(this);
//接收客戶端數(shù)據(jù),并回顯到自己的文本域
try {
//1.創(chuàng)建一個(gè)服務(wù)端的套接字socket
ServerSocket serverSocket = new ServerSocket(serverPort);
//2.等待客戶端的鏈接
Socket socket = serverSocket.accept();//客戶端對(duì)象
//3.獲取socket 通道的輸入流(輸入流是實(shí)現(xiàn)讀取數(shù)據(jù)的,一行一行讀取,因此用BufferedReader-->readLine
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//4.獲取socket 通道的輸出流(輸出流實(shí)現(xiàn)寫出數(shù)據(jù),也是寫一行,換一行,刷新)BufferedWriter-->new Line()
//什么時(shí)候需要寫出數(shù)據(jù)?當(dāng)用戶點(diǎn)擊發(fā)送按鈕時(shí)
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//循環(huán)讀取數(shù)據(jù),并把它拼接到文本域中
String line = null;
while ((line=br.readLine())!=null){
//將讀取的數(shù)據(jù)拼接到文本域中顯示
jta.append(line+System.lineSeparator());
}
//5.關(guān)閉serverSocket 通道
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
/******************TCP 服務(wù)端 end*****************/
}
//行為
/**
* 重新ActionListener中的1個(gè)方法,實(shí)現(xiàn)點(diǎn)擊 發(fā)送鍵 發(fā)送
* @param e
*/
@Override
public void actionPerformed(ActionEvent e) {
sendDataToSocket();
}
/**
* 重寫KeyListener中的3個(gè)方法,實(shí)現(xiàn)Enter鍵發(fā)送
* @param e
*/
@Override
public void keyPressed(KeyEvent e) {
//回車鍵
if (e.getKeyCode()== KeyEvent.VK_ENTER){
//發(fā)送數(shù)據(jù)到socket通道
sendDataToSocket();
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
//方法功能:發(fā)送數(shù)據(jù)到客戶端,并將內(nèi)容回顯到自己的文本域
public void sendDataToSocket(){
//1.獲取文本框中的內(nèi)容
String text = jtf.getText();
//2.拼接需要發(fā)送的數(shù)據(jù)內(nèi)容
text = "服務(wù)端對(duì)客戶端說:"+text;
//3.自己也需要顯示
jta.append(text+System.lineSeparator());
try {
//4.發(fā)送
bw.write(text);
bw.newLine();
bw.flush();
//5.清空文本框
jtf.setText("");
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
客戶端代碼:
package cn.qy.chat;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.*;
import java.net.Socket;
import java.util.Properties;
//說明:如果一個(gè)類,需要有界面的顯示,那么該類就需要繼承自JFrame,此時(shí),該類就可以被稱為一個(gè)“窗體類
//1.定義JFrame窗體中的組件
//2.在構(gòu)造方法中初始化組件
public class ClientChatMain extends JFrame implements ActionListener, KeyListener {
public static void main(String[] args) {
// 調(diào)用構(gòu)造器
new ClientChatMain();
}
//屬性
//文本域
private JTextArea jta;
//滾動(dòng)條
private JScrollPane jsp;
//面板
private JPanel jp;
//文本框
private JTextField jtf;
//按鈕
private JButton jb;
//流
BufferedReader br;
BufferedWriter bw;
//通信的IP和Port
private static int clientPort;
private static String clientIP;
//靜態(tài)代碼塊加載外部配置文件
//特點(diǎn)1:在類加載時(shí),自動(dòng)執(zhí)行
//特點(diǎn)2:一個(gè)類只會(huì)加載一次,因此靜態(tài)代碼塊只會(huì)執(zhí)行一次
static {
Properties prop = new Properties();
try {
prop.load(new FileReader("chat.properties"));
clientPort = Integer.parseInt(prop.getProperty("clientPort"));
clientIP = prop.getProperty("clientIP");
} catch (IOException e) {
e.printStackTrace();
}
}
//創(chuàng)建構(gòu)造器
public ClientChatMain(){
//初始化組件
//初始化文本域
jta = new JTextArea();
//設(shè)置文本域不可編輯
jta.setEditable(false);
//將文本域添加到滾動(dòng)條中,實(shí)現(xiàn)滾動(dòng)效果
jsp = new JScrollPane(jta);
//面板
jp = new JPanel();
jtf = new JTextField(15);
jb = new JButton("發(fā)送");
//將文本框與按鈕添加到面板中
jp.add(jtf);
jp.add(jb);
//將滾動(dòng)條與面板全部添加到窗體中
this.add(jsp, BorderLayout.CENTER);
this.add(jp, BorderLayout.SOUTH);
//設(shè)置 標(biāo)題 大小,位置,關(guān)閉,是否可見
this.setTitle("QQ 客戶端");
this.setSize(300,300);
this.setLocation(300,300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗體關(guān)閉,程序退出
this.setVisible(true);
/******************TCP 客戶端 start*****************/
//給發(fā)送按鈕綁定一個(gè)監(jiān)聽點(diǎn)擊事件
jb.addActionListener(this);
//給鍵盤綁定單擊事件
jtf.addKeyListener(this);
//接受服務(wù)端數(shù)據(jù),并回顯到自己的文本域
try {
//1.創(chuàng)建一個(gè)客戶端的套接字socket
Socket socket = new Socket(clientIP, clientPort);
//2.獲取socket 通道的輸入流
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//3.獲取socket 通道的輸出流
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//循環(huán)讀取數(shù)據(jù),并把它拼接到文本域中
String line =null;
while ((line=br.readLine())!=null){
jta.append(line+System.lineSeparator());
}
//4.關(guān)閉socket 通道
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
/******************TCP 客戶端 end*****************/
}
//行為
/**
* 重新ActionListener中的1個(gè)方法,實(shí)現(xiàn)點(diǎn)擊 發(fā)送鍵 發(fā)送
* @param e
*/
@Override
public void actionPerformed(ActionEvent e) {
sendDataToSocket();
}
/**
* 重寫KeyListener中的3個(gè)方法,實(shí)現(xiàn)Enter鍵發(fā)送
* @param e
*/
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode()==KeyEvent.VK_ENTER){
sendDataToSocket();
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
//方法功能:發(fā)送數(shù)據(jù)到服務(wù)端,并將內(nèi)容回顯到自己的文本域
private void sendDataToSocket(){
//1.獲取文本框中的內(nèi)容
String text = jtf.getText();
//2.拼接需要發(fā)送的數(shù)據(jù)內(nèi)容
text = "客戶端對(duì)服務(wù)端說:"+text;
//3.自己也需要顯示
jta.append(text+System.lineSeparator());
try {
//4.發(fā)送
bw.write(text);
bw.newLine();
bw.flush();
//5.清空文本框
jtf.setText("");
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
?啟動(dòng)時(shí),必須先啟動(dòng)服務(wù)端,再啟動(dòng)客戶端。
最終效果:
?
?
?
到了這里,關(guān)于用Java實(shí)現(xiàn)簡(jiǎn)易聊天室的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!