java實(shí)現(xiàn)實(shí)時(shí)通信聊天程序
利用TCP傳輸數(shù)據(jù),編寫客戶端和服務(wù)器的程序,實(shí)現(xiàn)兩個(gè)程序間的實(shí)時(shí)通信。
在每個(gè)程序中實(shí)現(xiàn)了實(shí)時(shí)的發(fā)送與接收數(shù)據(jù)的功能。
客戶端的io界面
服務(wù)器端的io界面
io演示
程序以兩端分別輸入close字符串作為結(jié)束標(biāo)識。在一端輸入close時(shí),終止發(fā)送、一端接收到close時(shí),終止接收。所演示的客戶端來自個(gè)人電腦IDEA調(diào)試運(yùn)行。服務(wù)器端來自阿里云服務(wù)器centos系統(tǒng)下的jdk環(huán)境。該程序需要用到j(luò)ava的 I/O 流、多線程、網(wǎng)絡(luò)編程的相關(guān)知識。
一、客戶端
由于發(fā)送和接收數(shù)據(jù)是并行的,為了使得時(shí)刻都能同時(shí)進(jìn)行接受與發(fā)送的功能,使用多線程,將接收和發(fā)送分別封裝為兩個(gè)Runnable實(shí)現(xiàn)類。獲取io信息。
ClientDemo類的源碼:
public class ClientDemo { ? ? public static Socket s; ? ? public static void main(String[] args) throws IOException, InterruptedException { ? ? ? ? s = new Socket("localhost", 10000); ? ? ? ?//此處的參數(shù)一填寫服務(wù)器端ip地址 ? ? ? ? System.out.println("連接成功"); ? ? ? ? Thread send = new Thread(new COUT()); ? ? ? ? Thread receive = new Thread(new CIN()); ? ? ? ? send.start(); ? ? ? ? receive.start(); ? ? ? ? send.join(); ? ? ? ?//發(fā)送和接收執(zhí)行完畢時(shí),關(guān)閉套接字 ? ? ? ? receive.join(); ? ? ? ?//因此待這兩個(gè)線程結(jié)束時(shí)才回到主線程執(zhí)行。 ? ? ? ? s.close(); ? ? } }
創(chuàng)建全局變量套接字s,在主進(jìn)程中給s進(jìn)行初始化,然后啟動(dòng)發(fā)送和接收功能的兩個(gè)線程。
Socket構(gòu)造時(shí)傳遞的兩個(gè)參數(shù),其一填寫服務(wù)器地址?;蛘咛顚憀ocalhost即127.0.0.1回送地址,本機(jī)即可運(yùn)行服務(wù)器端和客戶端進(jìn)行本地?cái)?shù)據(jù)傳輸。
其二是端口數(shù),需要保持客戶端和服務(wù)器端的套接字綁定的端口數(shù)一致。盡可能選用數(shù)量大的端口以免被占用,如果運(yùn)行時(shí)報(bào)錯(cuò)端口已占用可以嘗試更改端口數(shù),范圍在65536內(nèi)。
客戶端發(fā)送和接收類的源碼:
class CIN implements Runnable{ ? ? @Override ? ? public void run() { ? ? ? ?//接收模塊 ? ? ? ? try { ? ? ? ? ? ? InputStream is = ClientDemo.s.getInputStream();//通過全局套接字s獲取連接后的流 ? ? ? ? ? ? in(is); ? ? ? ? } ? ? ? ? catch (IOException o) { ? ? ? ? ? ? o.printStackTrace(); ? ? ? ? } ? ? } ? ? public static void in(InputStream is) throws IOException{ ? ? ? ? while(true){ ? ? ? ? ? ? byte[] bytes = new byte[1024]; ? ? ? ? ? ? int len = is.read(bytes); ? ? ? ? ? ? String line = new String(bytes,0,len); ? ? ? ? ? ? ? System.out.println("對方: ? "+line); ? ? ? ? ? ? if(line.equals("close")) ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? } } ? class COUT implements Runnable{ ? ? @Override ? ? public void run() { ? ? ? ?//發(fā)送模塊 ? ? ? ? try { ? ? ? ? ? ? OutputStream os = ClientDemo.s.getOutputStream();//套接字獲取流 ? ? ? ? ? ? out(os); ? ? ? ? } ? ? ? ? catch (IOException o){ ? ? ? ? ? ? o.printStackTrace(); ? ? ? ? } ? ? } ? ? public static void out(OutputStream os) throws IOException{ ? ? ? ? Scanner sc = new Scanner(System.in); ? ? ? ? while(true) { ? ? ? ? ? ? String line = sc.nextLine(); ? ? ? ? ? ? os.write(line.getBytes()); ? ? ? ? ? ? if(line.equals("close")) ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? sc.close(); ? ? } }
由于IO流都由socket創(chuàng)建,因此程序結(jié)束時(shí)需要關(guān)閉s即可。
二、服務(wù)器
ServerDemo類的源碼:
public class ServerDemo { ? ? public static ServerSocket ss; ? ? public static Socket s; ? ? ? public static void main(String[] args) throws IOException, InterruptedException { ? ? ? ? ss = new ServerSocket(10000); ? ? ? ?//監(jiān)聽端口10000,對應(yīng)客戶端套接字綁定的端口 ? ? ? ? s = ss.accept(); ? ? ? ?//提取監(jiān)聽套接字中的一個(gè)連接 ? ? ? ? System.out.println("連接成功"); ? ? ? ? Thread send = new Thread(new SOUT()); ? ? ? ? Thread receive = new Thread(new SIN()); ? ? ? ? send.start(); ? ? ? ? receive.start(); ? ? ? ? send.join(); ? ? ? ? receive.join(); ? ? ? ? ss.close(); ? ? } }
創(chuàng)建服務(wù)器套接字對象并監(jiān)聽,并接收連接請求。
此處的代碼與客戶端大同小異,完成連接后的代碼基本一致。
服務(wù)器端發(fā)送和接收類的源碼:
class SIN implements Runnable{ ? ? @Override ? ? public void run() { ? ? ? ? try { ? ? ? ? ? ? InputStream is = ServerDemo.s.getInputStream(); ? ? ? ? ? ? in(is); ? ? ? ? } ? ? ? ? catch (IOException o) { ? ? ? ? ? ? o.printStackTrace(); ? ? ? ? } ? ? } ? ? public static void in(InputStream is) throws IOException{ ? ? ? ? while(true){ ? ? ? ? ? ? byte[] bytes = new byte[1024]; ? ? ? ? ? ? int len = is.read(bytes); ? ? ? ? ? ? String line = new String(bytes,0,len); ? ? ? ? ? ? System.out.println("對方: ? "+line); ? ? ? ? ? ? if(line.equals("close")) ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? } } class SOUT implements Runnable{ ? ? @Override ? ? public void run() { ? ? ? ? try { ? ? ? ? ? ? OutputStream os = ServerDemo.s.getOutputStream(); ? ? ? ? ? ? out(os); ? ? ? ? } ? ? ? ? catch (IOException o){ ? ? ? ? ? ? o.printStackTrace(); ? ? ? ? } ? ? } ? ? public static void out(OutputStream os) throws IOException{ ? ? ? ? Scanner sc = new Scanner(System.in); ? ? ? ? while(true) { ? ? ? ? ? ? String line = sc.nextLine(); ? ? ? ? ? ? os.write(line.getBytes()); ? ? ? ? ? ? if(line.equals("close")) ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? sc.close(); ? ? } }
兩者代碼不同的地方在于由于套接字不同,返回的流實(shí)例不同。基本邏輯相同。
本地可同時(shí)運(yùn)行客戶端和服務(wù)器端,客戶端套接字綁定本地ip地址,“localhost或127.0.0.1。
先開啟服務(wù)器端進(jìn)行監(jiān)聽,然后打開客戶端向服務(wù)器端發(fā)起連接請求。連接成功后即可實(shí)時(shí)進(jìn)行聊天。在程序中以一行為信息單元,鍵入若干字符后換行發(fā)送。另一端即可收到信息。
在一端鍵入“close”發(fā)送即可關(guān)閉當(dāng)前程序的發(fā)送線程和接收程序的接收線程。待兩個(gè)程序的所有發(fā)送和接收都結(jié)束時(shí),關(guān)閉程序。
實(shí)測記錄:將服務(wù)器端程序發(fā)送至云服務(wù)器通過jdk運(yùn)行,并開啟程序監(jiān)聽,將客戶端的套接字指向服務(wù)器端的地址和監(jiān)聽端口。之后建立連接,可自由在兩端傳輸信息。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用Java和WebSocket實(shí)現(xiàn)網(wǎng)頁聊天室實(shí)例代碼
- java聊天室的實(shí)現(xiàn)代碼
- java socket實(shí)現(xiàn)聊天室 java實(shí)現(xiàn)多人聊天功能
- java實(shí)現(xiàn)自動(dòng)回復(fù)聊天機(jī)器人
- 基于Java Socket實(shí)現(xiàn)一個(gè)簡易在線聊天功能(一)
- Java基于socket實(shí)現(xiàn)簡易聊天室實(shí)例
- java Socket實(shí)現(xiàn)網(wǎng)頁版在線聊天
- java中UDP簡單聊天程序?qū)嵗a
- java實(shí)現(xiàn)一個(gè)簡單TCPSocket聊天室功能分享
- 基于java編寫局域網(wǎng)多人聊天室
相關(guān)文章
IDEA 自動(dòng)生成 JPA 實(shí)體類的圖文教程
這篇文章主要介紹了IDEA 自動(dòng)生成 JPA 實(shí)體類的圖文教程,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07java自定義任務(wù)類定時(shí)執(zhí)行任務(wù)示例 callable和future接口使用方法
Callable是類似于Runnable的接口,實(shí)現(xiàn)Callable接口的類和實(shí)現(xiàn)Runnable的類都是可被其它線程執(zhí)行的任務(wù)2014-01-01Java生產(chǎn)者消費(fèi)者模式實(shí)例分析
這篇文章主要介紹了Java生產(chǎn)者消費(fèi)者模式,結(jié)合實(shí)例形式分析了java生產(chǎn)者消費(fèi)者模式的相關(guān)組成、原理及實(shí)現(xiàn)方法,需要的朋友可以參考下2019-03-03Java數(shù)據(jù)結(jié)構(gòu)與算法實(shí)現(xiàn)遞歸與回溯
本文主要介紹了Java數(shù)據(jù)結(jié)構(gòu)與算法實(shí)現(xiàn)遞歸與回溯,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03SpringBoot開發(fā)項(xiàng)目,引入JPA找不到findOne方法的解決
這篇文章主要介紹了SpringBoot開發(fā)項(xiàng)目,引入JPA找不到findOne方法的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11