Java編程實(shí)現(xiàn)基于TCP協(xié)議的Socket聊天室示例
本文實(shí)例講述了Java編程實(shí)現(xiàn)基于TCP協(xié)議的Socket聊天室。分享給大家供大家參考,具體如下:
這里使用Socket套接字進(jìn)行編程,完成的是基于TCP可靠服務(wù)實(shí)現(xiàn)服務(wù)器與客戶端的雙通信。
Server服務(wù)器端:
package com.han; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.*; import java.net.*; import javax.swing.JDialog; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; /** * 本程序?qū)崿F(xiàn)了一個(gè)TCP程序的服務(wù)器編程部分。 * 使用Socket套接字進(jìn)行編程,完成的是基于TCP可靠服務(wù)實(shí)現(xiàn)與客戶端的雙通信。 * 客戶端的編程見本包中的類Client * @author HAN * */ @SuppressWarnings("serial") public class Server extends JDialog{ private BufferedReader reader; private PrintWriter writer; private ServerSocket server; private Socket socket; private JTextArea ta=new JTextArea(); private JScrollPane sp=new JScrollPane(ta); private JTextField tf=new JTextField(); Container cc; public Server(String title) { setTitle(title); addWindowListener(new WindowAdapter() { public void windowClosing (WindowEvent we) { dispose(); //撤銷dialog一切相關(guān)資源 System.exit(0); //正常退出程序 } }); cc=getContentPane(); setLayout(null); ta.setLineWrap(true); ta.setEditable(false); sp.setBounds(0,0,300,342); tf.setBounds(0,342,300,25); cc.add(sp); cc.add(tf); tf.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ try { writer=new PrintWriter(socket.getOutputStream(),true); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } writer.println(tf.getText()); ta.append("User1:"+tf.getText()+'\n'); tf.setText(""); } }); } void getserver(){ try{ server=new ServerSocket(8998); ta.append("服務(wù)器套接字已經(jīng)創(chuàng)建成功\n"); while(true){ ta.append("等待客戶機(jī)的連接\n"); socket=server.accept(); ta.append("客戶機(jī)已連接\n"); reader=new BufferedReader(new InputStreamReader(socket.getInputStream())); getClientMessage(); } }catch(Exception e){ e.printStackTrace(); } } private void getClientMessage(){ try { while(true){ String news=reader.readLine(); if(news!=null){ ta.append("User2:"+news+"\n"); }else{ ta.append("User2(客戶端) 已斷開鏈接\n"); break; } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try{ if(reader!=null){ reader.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(socket!=null){ try { socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { Server user1=new Server("User1"); user1.setBounds(0,0,300,400); user1.setResizable(false); user1.setVisible(true); user1.getserver(); } }
Client客戶端:
package com.han; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import javax.swing.*; /** * 本程序?qū)崿F(xiàn)了一個(gè)TCP程序的客戶端編程部分。 * 使用Socket套接字進(jìn)行編程,完成的是基于TCP可靠服務(wù)實(shí)現(xiàn)與服務(wù)器的雙通信。 * 服務(wù)器的編程見本包中的類Server * 可以在不同的平臺(tái)與不同的機(jī)器上運(yùn)行,只是要把代碼中寫的IP地址修改為運(yùn)行服務(wù)器程序Server的機(jī)器的IP地址。 * @author HAN * */ @SuppressWarnings("serial") public class Client extends JDialog{ private BufferedReader reader; private PrintWriter writer; private Socket socket; private JTextArea ta=new JTextArea(); private JScrollPane sp=new JScrollPane(ta); private JTextField tf=new JTextField(); Container cc; public Client(String title) { setTitle(title); addWindowListener(new WindowAdapter() { public void windowClosing (WindowEvent we) { dispose(); //撤銷dialog一切相關(guān)資源 System.exit(0); //正常退出程序 } }); cc=getContentPane(); setLayout(null); ta.setLineWrap(true); ta.setEditable(false); sp.setBounds(0,0,300,342); tf.setBounds(0,342,300,25); cc.add(sp); cc.add(tf); tf.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ writer.println(tf.getText()); ta.append("User2:"+tf.getText()+'\n'); tf.setText(""); } }); } private void connect(){ ta.append("嘗試連接\n"); try { socket=new Socket("192.168.1.3",8998); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { writer=new PrintWriter(socket.getOutputStream(),true); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } ta.append("完成連接\n"); } private void getClientMessage(){ try { reader=new BufferedReader(new InputStreamReader(socket.getInputStream())); while(true){ String news=reader.readLine(); if(news!=null){ ta.append("User1:"+news+"\n"); }else{ ta.append("User1(服務(wù)器) 已斷開鏈接,等待服務(wù)器重連之時(shí),重啟User2(客戶端)進(jìn)行通信\n"); break; } } } catch (IOException e) { // TODO Auto-generated catch block ta.append("User1(服務(wù)器) 已斷開鏈接,等待服務(wù)器重連之時(shí),重啟User2(客戶端)進(jìn)行通信\n"); e.printStackTrace(); } try{ if(reader!=null){ reader.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(socket!=null){ try { socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { Client user2=new Client("User2"); user2.setBounds(0,0,300,400); user2.setVisible(true); user2.setResizable(false); user2.connect(); user2.getClientMessage(); } }
更多關(guān)于java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java Socket編程技巧總結(jié)》、《Java文件與目錄操作技巧匯總》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
springboot整合SSE的項(xiàng)目實(shí)踐
SSE是一種可以主動(dòng)從服務(wù)端推送消息的技術(shù),本文主要介紹了springboot整合SSE的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09解決grails服務(wù)端口沖突的辦法(grails修改端口號)
grails中默認(rèn)的服務(wù)端口為8080,當(dāng)本機(jī)中需要同時(shí)啟動(dòng)兩個(gè)不同的項(xiàng)目時(shí),就會(huì)造成端口沖突,下面給出解決方法2013-12-12SpringBoot開發(fā)案例之打造私有云網(wǎng)盤的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot開發(fā)案例之打造私有云網(wǎng)盤的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04SpringCloud服務(wù)接口調(diào)用OpenFeign及使用詳解
這篇文章主要介紹了SpringCloud服務(wù)接口調(diào)用——OpenFeign,在學(xué)習(xí)Ribbon時(shí),服務(wù)間調(diào)用使用的是RestTemplate+Ribbon實(shí)現(xiàn),而Feign在此基礎(chǔ)上繼續(xù)進(jìn)行了封裝,使服務(wù)間調(diào)用變得更加方便,需要的朋友可以參考下2023-04-04java語言描述Redis分布式鎖的正確實(shí)現(xiàn)方式
這篇文章主要介紹了java語言描述Redis分布式鎖的正確實(shí)現(xiàn)方式,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12SpringBoot中Date格式化處理的三種實(shí)現(xiàn)
Spring Boot作為一個(gè)簡化Spring應(yīng)用開發(fā)的框架,提供了多種處理日期格式化的方法,本文主要介紹了SpringBoot中Date格式化處理實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03