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)識(shí)。在一端輸入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)知識(shí)。
一、客戶端
由于發(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ā)送和接收?qǐng)?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("對(duì)方: ? "+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,對(duì)應(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ù)器套接字對(duì)象并監(jiān)聽,并接收連接請(qǐng)求。
此處的代碼與客戶端大同小異,完成連接后的代碼基本一致。
服務(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("對(duì)方: ? "+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ā)起連接請(qǐng)求。連接成功后即可實(shí)時(shí)進(jìn)行聊天。在程序中以一行為信息單元,鍵入若干字符后換行發(fā)送。另一端即可收到信息。
在一端鍵入“close”發(fā)送即可關(guān)閉當(dāng)前程序的發(fā)送線程和接收程序的接收線程。待兩個(gè)程序的所有發(fā)送和接收都結(jié)束時(shí),關(guān)閉程序。
實(shí)測(cè)記錄:將服務(wù)器端程序發(fā)送至云服務(wù)器通過jdk運(yùn)行,并開啟程序監(jiān)聽,將客戶端的套接字指向服務(wù)器端的地址和監(jiān)聽端口。之后建立連接,可自由在兩端傳輸信息。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(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è)簡(jiǎn)易在線聊天功能(一)
- Java基于socket實(shí)現(xiàn)簡(jiǎn)易聊天室實(shí)例
- java Socket實(shí)現(xiàn)網(wǎng)頁版在線聊天
- java中UDP簡(jiǎn)單聊天程序?qū)嵗a
- java實(shí)現(xiàn)一個(gè)簡(jiǎn)單TCPSocket聊天室功能分享
- 基于java編寫局域網(wǎng)多人聊天室
相關(guān)文章
解析web.xml中在Servlet中獲取context-param和init-param內(nèi)的參數(shù)
本篇文章是對(duì)web.xml中在Servlet中獲取context-param和init-param內(nèi)的參數(shù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-07-07
java線程池ExecutorService超時(shí)處理小結(jié)
使用ExecutorService時(shí),設(shè)置子線程執(zhí)行超時(shí)是一個(gè)常見需求,本文就來詳細(xì)的介紹一下ExecutorService超時(shí)的三種方法,感興趣的可以了解一下2024-09-09
Idea連接數(shù)據(jù)庫并執(zhí)行SQL語句的方法示例
這篇文章主要介紹了Idea連接數(shù)據(jù)庫并執(zhí)行SQL語句的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Java?熱更新?Groovy?實(shí)踐及踩坑指南(推薦)
Apache的Groovy是Java平臺(tái)上設(shè)計(jì)的面向?qū)ο缶幊陶Z言,這門動(dòng)態(tài)語言擁有類似Python、Ruby和Smalltalk中的一些特性,可以作為Java平臺(tái)的腳本語言使用,這篇文章主要介紹了Java?熱更新?Groovy?實(shí)踐及踩坑指南,需要的朋友可以參考下2022-09-09
提高開發(fā)效率Live?Templates使用技巧詳解
這篇文章主要為大家介紹了提高開發(fā)效率Live?Templates使用技巧詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Spring源碼解析之BeanPostProcessor知識(shí)總結(jié)
今天給大家?guī)淼奈恼率荢pring的相關(guān)知識(shí),文章圍繞著BeanPostProcessor的使用展開,文中有非常詳細(xì)的介紹,需要的朋友可以參考下2021-06-06
SpringSecurity的TokenStore四種實(shí)現(xiàn)方式小結(jié)
本文主要介紹了SpringSecurity的TokenStore四種實(shí)現(xiàn)方式小結(jié),分別是InMemoryTokenStore,JdbcTokenStore,JwkTokenStore,RedisTokenStore,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01

