超详细带你用Java实现QQ的聊天功能
個(gè)人名片:
🐼作者簡(jiǎn)介:一名在校生
🐻???個(gè)人主頁(yè):hmm.
🕊?系列專欄:零基礎(chǔ)學(xué)java ----- 重識(shí)c語言
🐓每日一句:只要還有明天,今天就永遠(yuǎn)是起跑點(diǎn)。
?前言:🎊🎊🎊🎊🎊🎊🎊🎊🎊🎊🎊🎊🎊🎊🎊🎊
最近有許多小伙伴問小新有沒有好用的刷題網(wǎng)站,想提升一下自我能力**</font>
>**經(jīng)過小新縝密的思考與親身體驗(yàn),推薦超實(shí)用的**🎉(點(diǎn)擊訪問牛客網(wǎng))🎉
>*里面用豐富的大廠面試真題、各類算法由易到難層層遞進(jìn)、專項(xiàng)題庫(kù)應(yīng)有盡有,還不快來體驗(yàn)體驗(yàn)**🎏🎏🎏
?
文章目錄
- 第一步:完成界面搭建🐓
- 第二步:TPC通信的思路與步驟🐻???
-
- TCP協(xié)議🐶
- TCP 服務(wù)端 具體步驟(客戶端類似)🐮
- TCP通信步驟代碼實(shí)現(xiàn):🐸
- 點(diǎn)擊發(fā)送按鈕實(shí)現(xiàn)數(shù)據(jù)的傳輸🐺
- 第三步:實(shí)現(xiàn)回車鍵發(fā)送數(shù)據(jù)(客戶端類似)🐳
- 全部代碼:🐲
-
第一步:完成界面搭建🐓
要求:
- 創(chuàng)建兩個(gè)窗口:一個(gè)客戶端,一個(gè)服務(wù)端,完成代碼書寫
步驟:
1.定義JFrame窗體中的組件:文本域,滾動(dòng)條,面板,文本框,按鈕
//屬性//文本域private JTextArea jta;//滾動(dòng)條private JScrollPane jsp;//面板private JPanel jp;//文本框private JTextField jtf;//按鈕private JButton jb; 2.在構(gòu)造方法中初始化窗口的組件: //構(gòu)造方法public ServerChatMain(){//初始化組件jta = new JTextArea();//設(shè)置文本域默認(rèn)不可編輯jta.setEditable(false);//注意:需要將文本域添加到滾動(dòng)條中,實(shí)現(xiàn)滾動(dòng)效果jsp =new JScrollPane(jta);//初始化面板jp = new JPanel();jtf = new JTextField(10);jb=new JButton("發(fā)送");//注意:需要將文本框與按鈕添加到面板中jp.add(jtf);jp.add(jb);4.設(shè)置設(shè)置”標(biāo)題“,大小,位置,關(guān)閉,是否可見
//注意:需要設(shè)置”標(biāo)題“,大小,位置,關(guān)閉,是否可見this.setTitle("QQ聊天服務(wù)端");this.setSize(400,300);this.setLocation(700,300);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗體關(guān)閉,程序就退出this.setVisible(true);//設(shè)置窗體可見}這樣我們就完成了服務(wù)端的QQ聊天界面窗口搭建:
注意:JTextArea文本域是不可以書寫的
客戶端與服務(wù)端代碼類似,這里就不一一展示了
書寫完畢代碼,運(yùn)行效果如下圖:
第二步:TPC通信的思路與步驟🐻???
使用網(wǎng)絡(luò)編程完成數(shù)據(jù)點(diǎn)的傳輸(TCP,UDP協(xié)議)
TCP協(xié)議🐶
TCP 是面向連接的運(yùn)輸層協(xié)議。應(yīng)用程序在使用 TCP 協(xié)議之前,必須先建立 TCP 連接。在傳送數(shù)據(jù)完畢后,必須釋放已經(jīng)建立的 TCP 連接
每一條 TCP 連接只能有兩個(gè)端點(diǎn),每一條 TCP 連接只能是點(diǎn)對(duì)點(diǎn)的(一對(duì)一)
TCP 提供可靠交付的服務(wù)。通過 TCP 連接傳送的數(shù)據(jù),無差錯(cuò)、不丟失、不重復(fù),并且按序到達(dá)
TCP 提供全雙工通信。TCP 允許通信雙方的應(yīng)用進(jìn)程在任何時(shí)候都能發(fā)送數(shù)據(jù)。TCP 連接的兩端都設(shè)有發(fā)送緩存和接受緩存,用來臨時(shí)存放雙向通信的數(shù)據(jù)
面向字節(jié)流。TCP 中的“流”指的是流入到進(jìn)程或從進(jìn)程流出的字節(jié)序列
TCP 服務(wù)端 具體步驟(客戶端類似)🐮
具體步驟:
- 1.創(chuàng)建一個(gè)服務(wù)端的套接字
- 2.等待客戶端連接
- 3.獲取socket通道的輸入流(輸入六是實(shí)現(xiàn)讀取數(shù)據(jù)的,一行一行讀取)BufferedReader->readLine();
- 4.獲取socket 通道的輸出流(輸出流實(shí)現(xiàn)寫出數(shù)據(jù),也是寫一行換一行,刷新)BufferedWriter->newLine();
- 5.關(guān)閉socket 通道
TCP通信步驟代碼實(shí)現(xiàn):🐸
try {//1.創(chuàng)建一個(gè)服務(wù)端的套接字ServerSocket serverSocket = new ServerSocket(8888);//2.等待客戶端連接Socket socket = serverSocket.accept();//3.獲取socket通道的輸入流(輸入六是實(shí)現(xiàn)讀取數(shù)據(jù)的,一行一行讀取)BufferedReader->readLine();//InputStream in = socket.getInputStream();BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));//4.獲取socket 通道的輸出流(輸出流實(shí)現(xiàn)寫出數(shù)據(jù),也是寫一行換一行,刷新)BufferedWriter->newLine();//當(dāng)用戶點(diǎn)擊發(fā)送按鈕的時(shí)候?qū)懗鰯?shù)據(jù)BufferedWriter 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)閉socket 通道serverSocket.close();}catch (IOException e) {e.printStackTrace();}點(diǎn)擊發(fā)送按鈕實(shí)現(xiàn)數(shù)據(jù)的傳輸🐺
@Overridepublic void actionPerformed(ActionEvent actionEvent) {System.out.println("發(fā)送按鈕被點(diǎn)擊了");}步驟:
1.獲取文本框中發(fā)送的內(nèi)容
2.拼接需要發(fā)送的數(shù)據(jù)內(nèi)容
3.自己也要顯示
4.發(fā)送
5.清空文本框內(nèi)容
第三步:實(shí)現(xiàn)回車鍵發(fā)送數(shù)據(jù)(客戶端類似)🐳
首先要實(shí)現(xiàn)一個(gè)接口
public class ClientChatMain extends JFrame implements ActionListener, KeyListener { @Overridepublic void keyPressed(KeyEvent e) {//回車鍵// System.out.println(e);//發(fā)送數(shù)據(jù)到socket 同道中if(e.getKeyCode()==KeyEvent.VK_ENTER) {sendDataToSocket();}全部代碼:🐲
服務(wù)端:
package com.ithmm.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è)類,需要有界面的顯示,那么這個(gè)類就需要繼承JFrame,此時(shí),該類可以被成為一個(gè)窗體類 /*步驟:1.定義JFrame窗體中的組件2.在構(gòu)造方法中初始化窗口的組件3.使用網(wǎng)絡(luò)編程完成數(shù)據(jù)的鏈接(TPC,UDP 協(xié)議)4.實(shí)現(xiàn)"發(fā)送”按鈕的監(jiān)聽點(diǎn)擊事件5.實(shí)現(xiàn)“回車鍵”發(fā)送數(shù)據(jù)*/ 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;//輸出流(成員變量)private BufferedWriter bw = null;//服務(wù)端的端口號(hào)//private static int serverPort;//使用static靜態(tài)方法讀取外部京臺(tái)文件//static代碼塊特點(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"));//給屬性賦值Integer.parseInt(prop.getProperty("serverPort"));} catch (IOException e) {e.printStackTrace();}}*///構(gòu)造方法public ServerChatMain(){//初始化組件jta = new JTextArea();//設(shè)置文本域默認(rèn)不可編輯jta.setEditable(false);//注意:需要將文本域添加到滾動(dòng)條中,實(shí)現(xiàn)滾動(dòng)效果jsp =new JScrollPane(jta);//初始化面板jp = new JPanel();jtf = new JTextField(10);jb=new JButton("發(fā)送");//注意:需要將文本框與按鈕添加到面板中jp.add(jtf);jp.add(jb);//注意:需要將滾動(dòng)條與面板全部添加到窗體中,繼承了窗體的屬性,這里this就是窗體this.add(jsp, BorderLayout.CENTER);//BorderLayout--邊框布局this.add(jp,BorderLayout.SOUTH);//注意:需要設(shè)置”標(biāo)題“,大小,位置,關(guān)閉,是否可見this.setTitle("QQ聊天服務(wù)端");this.setSize(400,300);this.setLocation(700,300);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗體關(guān)閉,程序就退出this.setVisible(true);//設(shè)置窗體可見/**************** TCP 服務(wù)端 Start *********************///給發(fā)送按鈕綁定一個(gè)監(jiān)聽點(diǎn)擊事件jb.addActionListener(this);//給文本框綁定一個(gè)鍵盤點(diǎn)擊事件jtf.addKeyListener(this);try {//1.創(chuàng)建一個(gè)服務(wù)端的套接字ServerSocket serverSocket = new ServerSocket(8888);//2.等待客戶端連接Socket socket = serverSocket.accept();//3.獲取socket通道的輸入流(輸入六是實(shí)現(xiàn)讀取數(shù)據(jù)的,一行一行讀取)BufferedReader->readLine();//InputStream in = socket.getInputStream();BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));//4.獲取socket 通道的輸出流(輸出流實(shí)現(xiàn)寫出數(shù)據(jù),也是寫一行換一行,刷新)BufferedWriter->newLine();//當(dāng)用戶點(diǎn)擊發(fā)送按鈕的時(shí)候?qū)懗鰯?shù)據(jù)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)閉socket 通道serverSocket.close();}catch (IOException e) {e.printStackTrace();}/**************** TCP 服務(wù)端 end *********************/}@Overridepublic void actionPerformed(ActionEvent actionEvent) {//System.out.println("發(fā)送按鈕被點(diǎn)擊了");sendDataToSocket();}//行為@Overridepublic void keyPressed(KeyEvent e) {//回車鍵// System.out.println(e);//發(fā)送數(shù)據(jù)到socket 同道中if(e.getKeyCode()==KeyEvent.VK_ENTER) {sendDataToSocket();}}//定義一個(gè)方法,實(shí)現(xiàn)將數(shù)據(jù)發(fā)送到socket通道中private void sendDataToSocket(){//1.獲取文本框中發(fā)送的內(nèi)容String text = jtf.getText();//2.拼接需要發(fā)送的數(shù)據(jù)內(nèi)容text = "服務(wù)端對(duì)客戶端說:"+text;//3.自己也要顯示jta.append(text+System.lineSeparator());//4.發(fā)送try {bw.write(text);bw.newLine();//換行刷新bw.flush();//5.清空文本框內(nèi)容jtf.setText("");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void keyTyped(KeyEvent keyEvent) {}@Overridepublic void keyReleased(KeyEvent keyEvent) {}}客戶端:
import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Properties;//說明:如果一個(gè)類,需要有界面的顯示,那么這個(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;//s輸出流private BufferedWriter bw =null;//客戶端的IP地址// private static String clientIp;//客戶端的port端口號(hào)// private static int clientPort;//靜態(tài)代碼塊加載外部配置文件/* static{Properties prop = new Properties();try {prop.load(new FileReader("chat.properties"));clientIp = prop.getProperty("clientIp");clientPort =Integer.parseInt( prop.getProperty("clientPort"));} catch (IOException e) {e.printStackTrace();}}*///構(gòu)造方法public ClientChatMain(){//初始化組件jta = new JTextArea();//設(shè)置文本域默認(rèn)不可編輯jta.setEditable(false);//注意:需要將文本域添加到滾動(dòng)條中,實(shí)現(xiàn)滾動(dòng)效果jsp =new JScrollPane(jta);//初始化面板jp = new JPanel();jtf = new JTextField(10);jb=new JButton("發(fā)送");//注意:需要將文本框與按鈕添加到面板中jp.add(jtf);jp.add(jb);//注意:需要將滾動(dòng)條與面板全部添加到窗體中,繼承了窗體的屬性,這里this就是窗體this.add(jsp, BorderLayout.CENTER);//BorderLayout--邊框布局this.add(jp,BorderLayout.SOUTH);//注意:需要設(shè)置”標(biāo)題“,大小,位置,關(guān)閉,是否可見this.setTitle("QQ聊天客戶端");this.setSize(400,300);this.setLocation(700,300);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗體關(guān)閉,程序就退出this.setVisible(true);//設(shè)置窗體可見/**************** TCP 客戶端 Start *********************///給發(fā)送按鈕綁定一個(gè)監(jiān)聽點(diǎn)擊事件jb.addActionListener(this);//給文本框綁定一個(gè)鍵盤鍵jtf.addKeyListener(this);try {//1.創(chuàng)建一個(gè)客戶端的套接字(嘗試連接)Socket socket = new Socket("127.0.0.1",8888);//2.獲取socket通道的輸入流BufferedReader 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 *********************/}@Overridepublic void actionPerformed(ActionEvent e) {sendDataToSocket();}//行為@Overridepublic void keyPressed(KeyEvent e) {//回車鍵if(e.getKeyCode() == KeyEvent.VK_ENTER){//發(fā)送數(shù)據(jù)sendDataToSocket();}}private void sendDataToSocket(){//1.獲取文本框需要發(fā)送內(nèi)容String text = jtf.getText();//2.拼接內(nèi)容text = "客戶端對(duì)服務(wù)端說"+text;//3.自己顯示jta.append(text+System.lineSeparator());try {//4.發(fā)送bw.write(text);bw.newLine();//換行加刷新bw.flush();bw.write(text);//5.清空jtf.setText("");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyReleased(KeyEvent e) {}}接口類:
public interface addActistener { } public interface addActionListener { }
兄弟們,三連支持一下!!!
總結(jié)
以上是生活随笔為你收集整理的超详细带你用Java实现QQ的聊天功能的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ext2.0中EditorGridPan
- 下一篇: ExtJS之EditorGridPane