最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
java即時(shí)通訊代碼的簡(jiǎn)單介紹

即時(shí)通訊IM系統(tǒng)開發(fā)

我于2014年開啟即時(shí)通訊的開發(fā)之路,歷經(jīng)從服務(wù)端到客戶端,從第三方到自研,經(jīng)歷過諸多的研發(fā)難題,都一一破解?,F(xiàn)將經(jīng)驗(yàn)總結(jié)如下,希望對(duì)行業(yè)內(nèi)從事IM開發(fā)的程序員有所幫助。

成都創(chuàng)新互聯(lián)是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來公司不斷探索創(chuàng)新,始終堅(jiān)持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過去的十載時(shí)間我們累計(jì)服務(wù)了上千家以及全國政企客戶,如成都三維植被網(wǎng)等企業(yè)單位,完善的項(xiàng)目管理流程,嚴(yán)格把控項(xiàng)目進(jìn)度與質(zhì)量監(jiān)控加上過硬的技術(shù)實(shí)力獲得客戶的一致稱揚(yáng)。

①P2P方式

P2P方式多用于局域網(wǎng)內(nèi)聊天,這種方式在有種種限制和不便。一方面它只適合在線的點(diǎn)對(duì)點(diǎn)消息傳輸,對(duì)離線,群組等支持不夠。另一方面由于 NAT 的存在,使得不同局域網(wǎng)內(nèi)機(jī)器互聯(lián)難度大大上升,在某些網(wǎng)絡(luò)類型(對(duì)稱NAT)下無法建立連接。使用P2P方式的軟件在啟動(dòng)后一般做兩件事情:

1、進(jìn)行UDP廣播:發(fā)送自己信息和接受同局域網(wǎng)內(nèi)其他端信息。

2、開啟TCP監(jiān)聽:等待其他端進(jìn)行連接。

②服務(wù)器中轉(zhuǎn)方式

大部分的互聯(lián)網(wǎng)IM產(chǎn)品都采用服務(wù)器中轉(zhuǎn)這種方式進(jìn)行消息傳輸,相對(duì)于P2P的方式,具有有以下的優(yōu)點(diǎn):

1、支持更多P2P無法支持或支持不好的業(yè)務(wù),如離線消息,群組,聊天室。

2、方便業(yè)務(wù)邏輯的拓展和新舊版本的兼容,當(dāng)然它也有自己的問題,就是服務(wù)器架構(gòu)復(fù)雜,并發(fā)要求高。

通過以上的比較,建議我們?cè)陂_發(fā)IM系統(tǒng)的時(shí)候使用服務(wù)器中轉(zhuǎn)的方式。

IM的網(wǎng)絡(luò)連接方式有基于TCP的長(zhǎng)連接和基于HTTP短連接兩種:

①基于TCP的長(zhǎng)連接

基于TCP長(zhǎng)連接則能夠更好地支持大批量用戶,問題是客戶端和服務(wù)器的實(shí)現(xiàn)比較復(fù)雜。也有一些改進(jìn),比如下行使用MQTT進(jìn)行服務(wù)器通知/消息的下發(fā),上行使用HTTP短連接進(jìn)行指令和消息的上傳。這種方式能夠保證下行消息/指令的及時(shí)性,但是在弱網(wǎng)絡(luò)下上行慢的問題還是比較嚴(yán)重,早期的來往就是基于這種方式。

②基于HTTP短連接

常見于WEB IM系統(tǒng)(現(xiàn)在很多WEBIM都是基于WebSocket實(shí)現(xiàn)),它的優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單,方便開發(fā)上手,問題是流量大,服務(wù)器負(fù)載較大,消息及時(shí)性無法很好地保證,對(duì)大規(guī)模的用戶量支持不夠,適合小型的IM系統(tǒng)。

IM常見的協(xié)議有:XMPP,MQTT,私有協(xié)議。各種協(xié)議優(yōu)缺點(diǎn)情況如下:

①XMPP協(xié)議

優(yōu)點(diǎn):協(xié)議開源,可拓展性強(qiáng),在各個(gè)端(有各種語言的實(shí)現(xiàn),對(duì)于前期入門級(jí)的開發(fā)者是很好的選擇,方便進(jìn)入IM開發(fā)的程序員快速上手。

缺點(diǎn):XML表現(xiàn)力弱,有太多冗余信息,流量大。

常見案例:Gtalk、新浪微博、Facebook。

②MQTT協(xié)議

優(yōu)點(diǎn):協(xié)議簡(jiǎn)單,流量少。

缺點(diǎn):不是一個(gè)專門為IM設(shè)計(jì)的協(xié)議,多使用于推送。

③私有協(xié)議

幾乎所有主流的IM APP都是使用私有協(xié)議。

優(yōu)點(diǎn):高效,節(jié)約流量(一般使用二進(jìn)制協(xié)議),安全性高,難以破解。

缺點(diǎn):開發(fā)初期沒有現(xiàn)有樣列可以參考,對(duì)于參與IM開發(fā)的程序員的要求比較高。

常見案例:微信、釘釘。

根據(jù)以上的對(duì)比,我們得出結(jié)果,一個(gè)好的協(xié)議需要滿足高效、簡(jiǎn)潔、節(jié)約流量、易于拓展等要求,同時(shí)又能夠和當(dāng)前的開發(fā)團(tuán)隊(duì)的技術(shù)堆棧匹配,不能選擇一個(gè)他們很難上手的。

這里再提一下,我當(dāng)時(shí)開發(fā)IM系統(tǒng)的時(shí)候,上手用的是XMPP,在使用的過程中發(fā)現(xiàn)了很多問題,踩了很多坑。

①實(shí)時(shí)性原則

消息實(shí)時(shí)到達(dá)接收方,如果用戶在線,則消息實(shí)時(shí)到達(dá),如果用戶不在線,則消息在用戶登錄后到達(dá)。由于網(wǎng)絡(luò)波動(dòng),以及移動(dòng)端操作系統(tǒng)對(duì)應(yīng)用前后臺(tái)切換的管理,如何實(shí)現(xiàn)用戶連接管理、消息實(shí)時(shí)推送,推送失敗的處理方式,客戶端重連機(jī)制,消息如何補(bǔ)齊等,都需要IM系統(tǒng)考慮。由于TCP開發(fā)略微復(fù)雜,早期的基于HTTP短輪詢、長(zhǎng)輪詢的低效的技術(shù)方案,也無法達(dá)到實(shí)時(shí)性的要求。

②可靠性原則

是指我們經(jīng)常聽到的“消息送達(dá)”,通常用消息的不丟失和不重復(fù)兩個(gè)技術(shù)指標(biāo)來表示??煽啃允且_保消息被發(fā)送后,能夠被接收者收到。由于網(wǎng)絡(luò)環(huán)境的復(fù)雜性,以及用戶在線的不確定性,消息的可靠性(不丟失、不重復(fù))是IM系統(tǒng)的核心指標(biāo),也是IM系統(tǒng)實(shí)現(xiàn)中的難點(diǎn)之一。總體來說,IM系統(tǒng)的消息“可靠性”,通常就是指聊天消息投遞的可靠性(準(zhǔn)確的說,這個(gè)“消息”是廣義的,因?yàn)檫€存用戶看不見的各種指令和通知,包括但不限于進(jìn)群退群通知、好友添加通知等,為了方便描述,統(tǒng)稱“消息”)。

從消息發(fā)送者和接收者用戶行為來講,消息“可靠性”應(yīng)該分為以下幾種情況:

1、發(fā)送失?。簩?duì)于這種情況要感知到,明確反饋給發(fā)送方。如果此消息沒有發(fā)送成功,發(fā)送方可以選擇重試或者稍后再試。

2、發(fā)送成功:如果接收方處在“在線”狀態(tài),應(yīng)該立即收到此消息。如果接收方處在“離線”狀態(tài)不能收到消息,一旦上線則立刻收到消息。

3、消息不能重復(fù):簡(jiǎn)言之就是發(fā)送的一條消息不能被重復(fù)收到多次。

③一致性原則

系統(tǒng)中要重視消息的時(shí)序問題,不能出現(xiàn)發(fā)送的消息順序顛倒的問題。通常出現(xiàn)時(shí)序的問題有以下的原因:

1、網(wǎng)絡(luò)傳輸延遲導(dǎo)致時(shí)序不一致。不同用戶發(fā)送的消息到達(dá)服務(wù)器的延時(shí)差異較大,給消息時(shí)序性帶來挑戰(zhàn)。早期開發(fā)過程中經(jīng)常會(huì)遇到這種問題。

2、分布式系統(tǒng)的出現(xiàn)導(dǎo)致時(shí)序不一致。IM系統(tǒng)模塊眾多,接入層、消息邏輯層等、每層都分布式集群化,這些應(yīng)用分布在不同的機(jī)器上,如何保證時(shí)序是個(gè)難點(diǎn)。

④擴(kuò)展性原則

擴(kuò)展性是IM系統(tǒng)后期要考慮的問題,包括功能的擴(kuò)展,服務(wù)器的擴(kuò)展等,這次就先不展開闡述。

Mina和Netty都是Java領(lǐng)域高性能和高可伸縮性網(wǎng)絡(luò)應(yīng)用程序的網(wǎng)絡(luò)應(yīng)用框架。

Mina是 Apache 組織的項(xiàng)目,它為開發(fā)高性能和高可用性的網(wǎng)絡(luò) 應(yīng)用程序提供的框架。當(dāng)前的Mina版本支持基于 Java NIO 技術(shù)的 TCP/UDP 應(yīng)用程序開發(fā)、串口通訊程序。目前正在使用 Mina的 軟件有:Apache Directory Project、AsyncWeb、AMQP(Advanced Message Queuing Protocol)、RED5 Server(Macromedia Flash Media RTMP)、ObjectRADIUS、Openfire等。

Netty是由JBOSS提供的一個(gè)java開源框架。Netty提供異步的、 事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架和工具,用以快速開發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序。也就是說Netty是一個(gè)基于NIO的客戶端和服務(wù)器端框架,使用Netty可以確保你快速和簡(jiǎn)單的開發(fā)出一個(gè)網(wǎng)絡(luò)應(yīng)用。

雖然我使用過Mina,但是建議開發(fā)選型上使用Netty 。因?yàn)镹etty有對(duì)google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi)。Mina更新到2.0就不再更新了,而Netty一直在更新,目前最新發(fā)布的版本已經(jīng)更新到4.1,從版本更新角度可以看出Netty的社區(qū)很活躍,修復(fù)問題一直在持續(xù),這將對(duì)我們選擇它進(jìn)行開發(fā)帶來很多便利。

單體Netty IM系統(tǒng),可以支持10萬并發(fā),如果機(jī)器性能良好的情況下可以超過10萬。

分布式的Netty IM系統(tǒng),可以支持更高的并發(fā)數(shù)。各組件的功能如下:

①IM Server 連接器:主要用來負(fù)責(zé)維持和客戶端的TCP連接。

②緩存:負(fù)責(zé)用戶、用戶綁定關(guān)系、用戶群組關(guān)系的緩存。 緩存臨時(shí)數(shù)據(jù)、加快讀速度。可以做成集群方式。

③數(shù)據(jù)庫:用戶、群組、離線消息。可以做成集群方式。

④消息隊(duì)列:用戶狀態(tài)廣播、群組消息廣播??梢宰龀杉悍绞健?/p>

開發(fā)環(huán)境推薦使用netty-4.1.30這個(gè)版本,jdk使用1.8及以上版本。如下所示:

io.netty

netty-all

4.1.30.Final

①開發(fā)框架采用Netty + Spring(Spring4.x)。

②Spring采用Spring cloud。基于restful 短連接的分布式微服務(wù)架構(gòu),完成用戶在線管理、單點(diǎn)登錄系統(tǒng)。

③消息隊(duì)列采用rocketMQ 高速隊(duì)列,整流作用。

④數(shù)據(jù)庫采用MYSQL。

⑤協(xié)議JSON +自定義數(shù)據(jù)包采用Fastjson。

基于Netty的IM開源代碼在網(wǎng)上有很多,這里就不列舉了,可以自行去git上下載。我認(rèn)為關(guān)鍵是把概念理清楚,技術(shù)堆棧選好,總體框架定好,接下來就是開發(fā)一個(gè)適合中小企業(yè)的IM系統(tǒng)了,但是要考慮到后期的擴(kuò)展性,因?yàn)橐粋€(gè)好的產(chǎn)品不能自己用,要讓更多的人使用。

怎樣用java web和websocket實(shí)現(xiàn)網(wǎng)頁即時(shí)通訊

使用7z格式壓縮上傳

下載1:

下載2: att.newsmth.net/att.php?p.75.25665.766.7z

Java版源代碼下載:

(有些網(wǎng)友對(duì)C++如何實(shí)現(xiàn)感興趣,推薦一下Poco帶的WebSocket功能,把Java源代碼翻譯成C++就行了)

1. 說明:

utf8版本,支持各種語言版本的windows系統(tǒng)

程序內(nèi)嵌數(shù)據(jù)庫

用戶帳號(hào)非明文存儲(chǔ)

在Firefox/Chrome瀏覽器測(cè)試通過,建議使用Chrome,F(xiàn)irefox不支持mp3的消息提示音

2. 現(xiàn)有功能

注冊(cè)/登錄/搜索/添加好友(需要雙方互相添加對(duì)方為好友,才能互相聊天)

抖動(dòng)窗口

兩種狀態(tài),登錄/離線

3.可擴(kuò)展的功能

使用Windows域用戶帳號(hào),無需注冊(cè)

收發(fā)離線信息

查看歷史信息

新消息提示

群聊

共享文件

4. (可能)存在的問題

并發(fā)性未作充分測(cè)試

添加好友的確認(rèn)

5. 適用的場(chǎng)景

學(xué)校

小公司

6.使用

解壓后雙擊執(zhí)行start.bat,將自動(dòng)進(jìn)入初始界面,如下圖

默認(rèn)使用80端口,若80端口已被占用,修改start.bat中的setserver_port=80

雙擊左上角圖標(biāo),彈出對(duì)話框,可以選擇注冊(cè)

注冊(cè)成功

登錄

搜索好友,如不提供搜索條件,則返回所有已注冊(cè)用戶

添加好友

添加好友提示

聊天

Java語言寫段簡(jiǎn)單,但又有技術(shù)含量的即時(shí)通訊代碼,不勝感激之情溢于滿天下

這里有一個(gè)簡(jiǎn)單的模擬通訊 要先運(yùn)行服務(wù)器端 再運(yùn)行客戶端 否則會(huì)報(bào)錯(cuò):

服務(wù)器端代碼:

package?com.test3;

import?java.net.*;

import?java.io.*;

import?javax.swing.*;

import?java.awt.*;

import?java.awt.event.*;

public?class?Server2?extends?JFrame?implements?ActionListener?,?KeyListener?{

JTextArea?jta=null;

JScrollPane?jsp=null;

JTextField?jtf=null;

JButton?jb=null;

JPanel?jp=null;

InputStreamReader?isr=null;

BufferedReader?br=null;

PrintWriter?pw=null;

Socket?s;

String?jtatext="";

public?static?void?main(String[]?args)?{

//?TODO?Auto-generated?method?stub

Server2?sv2=new?Server2();

}

public?Server2(){

jta=new?JTextArea();

jta.setEditable(false);

jsp=new?JScrollPane(jta);

jtf=new?JTextField(10);

jtf.addKeyListener(this);

jb=new?JButton("發(fā)送");

jb.addActionListener(this);

jp=new?JPanel();

jp.add(jtf);

jp.add(jb);

this.add(jsp,"Center");

this.add(jp,"South");

this.setSize(300,300);

this.setLocationRelativeTo(this);

this.setTitle("服務(wù)器端");

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setVisible(true);

try{

ServerSocket?ss=new?ServerSocket(9999);

s=ss.accept();

isr=new?InputStreamReader(s.getInputStream());

br=new?BufferedReader(isr);

pw=new?PrintWriter(s.getOutputStream(),true);

while(true){

String?info=br.readLine();

jta.append("客戶端對(duì)服務(wù)器說:???"+info+"\r\n");

// this.jta.setText(jtatext);

}

}catch(Exception?e){

e.printStackTrace();

}

}

@Override

public?void?actionPerformed(ActionEvent?e)?{

if(e.getSource()==jb){

try?{

pw.println(jtf.getText());

jta.append("服務(wù)器對(duì)客戶端說:???"+jtf.getText()+"\r\n");

// jta.setText(jtatext);

jtf.setText("");

}?catch?(Exception?e1)?{

//?TODO?Auto-generated?catch?block

e1.printStackTrace();

}

}

}

@Override

public?void?keyTyped(KeyEvent?e)?{}

@Override

public?void?keyPressed(KeyEvent?e)?{

if(e.getKeyCode()==KeyEvent.VK_ENTER){

try?{

pw.println(jtf.getText());

jta.append("服務(wù)器對(duì)客戶端說:???"+jtf.getText()+"\r\n");

jtf.setText("");

}?catch?(Exception?e1)?{

e1.printStackTrace();

}

}

}

@Override

public?void?keyReleased(KeyEvent?e)?{}

}

客戶端代碼:

package?com.test3;

import?java.net.*;

import?java.io.*;

import?javax.swing.*;

import?java.awt.*;

import?java.awt.event.*;

public?class?Client2?extends?JFrame?implements?ActionListener?,KeyListener?{

JTextArea?jta=null;

JScrollPane?jsp=null;

JTextField?jtf=null;

JButton?jb=null;

JPanel?jp=null;

String?jtatext="";

Socket?s;

PrintWriter?pw=null;

InputStreamReader?isr=null;

BufferedReader?br=null;

public?static?void?main(String[]?args)?{

//?TODO?Auto-generated?method?stub

Client2?sv2=new?Client2();

}

public?Client2(){

jta=new?JTextArea();

jta.setEditable(false);

jsp=new?JScrollPane(jta);

jtf=new?JTextField(10);

jtf.addKeyListener(this);

jb=new?JButton("發(fā)送");

jb.addActionListener(this);

jp=new?JPanel();

jp.add(jtf);

jp.add(jb);

this.add(jsp,"Center");

this.add(jp,"South");

this.setSize(300,300);

this.setLocationRelativeTo(this);

this.setTitle("客戶端");

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setVisible(true);

try?{

?s=new?Socket("127.3.3.3",9999);

?isr=new?InputStreamReader(s.getInputStream());

?br=new?BufferedReader(isr);

?pw=new?PrintWriter(s.getOutputStream(),true);

?

?while(true){

?String?info=br.readLine();?

jta.append("服務(wù)器對(duì)客戶端說:???"+info+"\r\n");

?

?}

}?catch?(Exception?e)?{

//?TODO?Auto-generated?catch?block

e.printStackTrace();

}

}

@Override

public?void?actionPerformed(ActionEvent?e)?{

if(e.getSource()==jb){

try?{

pw.println(this.jtf.getText());

jta.append("客戶端對(duì)服務(wù)器說:???"+jtf.getText()+"\r\n");

jtf.setText("");

}?catch?(Exception?e1)?{

//?TODO?Auto-generated?catch?block

e1.printStackTrace();

}

}

}

public?void?keyTyped(KeyEvent?e)?{}

public?void?keyPressed(KeyEvent?e)?{

if(e.getKeyCode()==KeyEvent.VK_ENTER){

try?{

pw.println(this.jtf.getText());

jta.append("客戶端對(duì)服務(wù)器說:???"+jtf.getText()+"\r\n");

jtf.setText("");

}?catch?(Exception?e1)?{

//?TODO?Auto-generated?catch?block

e1.printStackTrace();

}

}

}

public?void?keyReleased(KeyEvent?e)?{}

}

我在用java做一個(gè)簡(jiǎn)單的即時(shí)通訊工具,自學(xué)的所以很多都不會(huì),希望可以幫幫我

package service_client_for_many;

import java.awt.BorderLayout;

import java.awt.Font;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.Vector;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;

import javax.swing.JTextField;

/**

* 雙工服務(wù)器,多人 本服務(wù)器默認(rèn)不提供服務(wù),而是在客戶端連接時(shí)創(chuàng)建獨(dú)立線程負(fù)責(zé)業(yè)務(wù)

**/

public class MutilServer implements ActionListener {

private JFrame frame;

/** 邊界布局的主面板 */

private JPanel panelMain;

private JPanel panelDown;

private JTextArea ta;

private JTextField txt;

private JButton but;

private JScrollPane jsp;

private Font font;

/**

* 當(dāng)前服務(wù)器使用端口

*/

private int port = 6666;

/**

* 遠(yuǎn)程客戶端的IP

*/

private String clientIp;

/**

* 記錄所有正在工作的服務(wù)員的登記表

*/

private VectorWaiter dengJiBiao;

public MutilServer() {

frame = new JFrame("雙工多人服務(wù)器");

panelMain = new JPanel(new BorderLayout());

panelDown = new JPanel();

ta = new JTextArea();

txt = new JTextField(20);

but = new JButton("發(fā)送");

jsp = new JScrollPane(ta);

// 粘貼界面

panelDown.add(txt);

panelDown.add(but);

panelMain.add(jsp, BorderLayout.CENTER);

panelMain.add(panelDown, BorderLayout.SOUTH);

// 字體

font = new Font("宋體", Font.BOLD, 18);

txt.setFont(font);

ta.setFont(font);

but.setFont(font);

// 文本域只讀

ta.setEditable(false);

// 按鈕添加監(jiān)聽

but.addActionListener(this);

frame.add(panelMain);

frame.setBounds(100, 300, 400, 400);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 關(guān)閉窗體時(shí)結(jié)束程序

frame.setAlwaysOnTop(true);// 永遠(yuǎn)在所有窗體最上

frame.setVisible(true);

// 創(chuàng)建登記表

dengJiBiao = new VectorWaiter();

// 光標(biāo)給消息文本框

txt.requestFocus();

createServer();

}

/**

* 顯示文本到文本域,并且追加一個(gè)換行

*

* @param msg

* 要顯示的文本

*/

public void showTxt(String msg) {

ta.append(msg + "\n");

}

public static void main(String[] args) {

new MutilServer();

}

// 動(dòng)作監(jiān)聽

public void actionPerformed(ActionEvent e) {

if (e.getSource() == but) {// 發(fā)送

txt.requestFocus();

String str = txt.getText().trim();

if(str.length()==0){

showTxt("不可以發(fā)送空消息");

return;

}

if(dengJiBiao.size()==0){

showTxt("當(dāng)前木有客戶連接,無法發(fā)送信息");

return;

}

str ="服務(wù)器消息:"+str;

//找到所有登記表中的服務(wù)員,實(shí)現(xiàn)群發(fā)

for (int i = 0; i dengJiBiao.size(); i++) {

Waiter w = dengJiBiao.get(i);//得到當(dāng)前循環(huán)的服務(wù)員

w.send(str);

}

// 清空文本框,得到焦點(diǎn)

txt.setText("");

}

}

/**

* 啟動(dòng)網(wǎng)絡(luò)服務(wù)器

*/

public void createServer() {

showTxt("正在啟動(dòng)服務(wù)器,使用本機(jī)" + port + "端口...");

try {

ServerSocket server = new ServerSocket(port);

showTxt("服務(wù)器啟動(dòng)成功,開始監(jiān)聽網(wǎng)絡(luò)連接...");

while (true) {

Socket jiaoYi = server.accept();

// 每得到一個(gè)交易,就是來了一個(gè)客戶端.需要交給一個(gè)新的服務(wù)員去維護(hù)處理

new Waiter(jiaoYi, dengJiBiao, this);

}

} catch (IOException e) {

showTxt("服務(wù)器啟動(dòng)失敗,可能端口被占用");

}

}

}

package service_client_for_many;

import java.awt.BorderLayout;

import java.awt.Font;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

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.net.UnknownHostException;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;

import javax.swing.JTextField;

/** 客戶端雙工 */

public class MyClient implements ActionListener{

private JFrame frame;

/** 邊界布局的主面板 */

private JPanel panelMain;

private JPanel panelDown;

private JTextArea ta;

private JTextField txt;

private JButton but;

private JScrollPane jsp;

private Font font;

/**

* 服務(wù)器IP

*/

private String ip = "192.168.10.239";

/**

* 服務(wù)器端口

*/

private int port = 6666;

private BufferedReader br;

private BufferedWriter bw;

public MyClient() {

frame = new JFrame("雙工客戶端1");

panelMain = new JPanel(new BorderLayout());

panelDown = new JPanel();

ta = new JTextArea();

txt = new JTextField(20);

but = new JButton("發(fā)送");

jsp = new JScrollPane(ta);

// 粘貼界面

panelDown.add(txt);

panelDown.add(but);

panelMain.add(jsp, BorderLayout.CENTER);

panelMain.add(panelDown, BorderLayout.SOUTH);

// 字體

font = new Font("宋體", Font.BOLD, 18);

txt.setFont(font);

ta.setFont(font);

but.setFont(font);

// 文本域只讀

ta.setEditable(false);

//按鈕添加監(jiān)聽

but.addActionListener(this);

frame.add(panelMain);

frame.setBounds(500, 200, 400, 400);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 關(guān)閉窗體時(shí)結(jié)束程序

frame.setAlwaysOnTop(true);// 永遠(yuǎn)在所有窗體最上

frame.setVisible(true);

// 光標(biāo)給消息文本框

txt.requestFocus();

linkServer();

}

/** 顯示文本到文本域,并且追加一個(gè)換行

* @param msg 要顯示的文本

*/

public void showTxt(String msg) {

ta.append(msg+"\n");

}

public static void main(String[] args) {

new MyClient();

}

//動(dòng)作監(jiān)聽

public void actionPerformed(ActionEvent e) {

if (e.getSource() == but) {// 發(fā)送

if (bw == null) {

showTxt("當(dāng)前沒有客戶端連接,無法發(fā)送消息");

return;

}

String s = txt.getText().trim();// 得到文本框要發(fā)送的文字,去掉兩端空格

if (s.length() == 0) {

showTxt("不可以發(fā)送空消息");

return;

}

showTxt("我說:" + s);

try {

bw.write(s + "\n");// 發(fā)送網(wǎng)絡(luò)消息給對(duì)方

bw.flush();// 清空緩沖

} catch (IOException e1) {

showTxt("信息:" + s + " 發(fā)送失敗");

}

// 清空文本框,得到焦點(diǎn)

txt.setText("");

txt.requestFocus();

}

}

/**

* 連接服務(wù)器

*/

public void linkServer(){

showTxt("準(zhǔn)備連接服務(wù)器"+ip+":"+port);

try {

Socket jiaoYi = new Socket(ip,port);

showTxt("連接服務(wù)器成功,開始進(jìn)行通訊");

// 得到輸入和輸出

br = new BufferedReader(new InputStreamReader(

jiaoYi.getInputStream()));

bw = new BufferedWriter(new OutputStreamWriter(

jiaoYi.getOutputStream()));

String s = null;

while ((s = br.readLine()) != null) {

showTxt( s);

}

} catch (UnknownHostException e) {

showTxt("連接服務(wù)器失敗,網(wǎng)絡(luò)連通錯(cuò)誤");

} catch (IOException e) {

showTxt("與服務(wù)器通訊失敗,已經(jīng)斷開連接");

}

showTxt("關(guān)閉");

}

}

package service_client_for_many;

import java.awt.BorderLayout;

import java.awt.Font;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

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.net.UnknownHostException;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTextArea;

import javax.swing.JTextField;

/** 客戶端雙工 */

public class MyClient2 implements ActionListener{

private JFrame frame;

/** 邊界布局的主面板 */

private JPanel panelMain;

private JPanel panelDown;

private JTextArea ta;

private JTextField txt;

private JButton but;

private JScrollPane jsp;

private Font font;

/**

* 服務(wù)器IP

*/

private String ip = "192.168.10.239";

/**

* 服務(wù)器端口

*/

private int port = 6666;

private BufferedReader br;

private BufferedWriter bw;

public MyClient2() {

frame = new JFrame("雙工客戶端2");

panelMain = new JPanel(new BorderLayout());

panelDown = new JPanel();

ta = new JTextArea();

txt = new JTextField(20);

but = new JButton("發(fā)送");

jsp = new JScrollPane(ta);

// 粘貼界面

panelDown.add(txt);

panelDown.add(but);

panelMain.add(jsp, BorderLayout.CENTER);

panelMain.add(panelDown, BorderLayout.SOUTH);

// 字體

font = new Font("宋體", Font.BOLD, 18);

txt.setFont(font);

ta.setFont(font);

but.setFont(font);

// 文本域只讀

ta.setEditable(false);

//按鈕添加監(jiān)聽

but.addActionListener(this);

frame.add(panelMain);

frame.setBounds(900, 200, 400, 400);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 關(guān)閉窗體時(shí)結(jié)束程序

frame.setAlwaysOnTop(true);// 永遠(yuǎn)在所有窗體最上

frame.setVisible(true);

// 光標(biāo)給消息文本框

txt.requestFocus();

linkServer();

}

/** 顯示文本到文本域,并且追加一個(gè)換行

* @param msg 要顯示的文本

*/

public void showTxt(String msg) {

ta.append(msg+"\n");

}

public static void main(String[] args) {

new MyClient2();

}

//動(dòng)作監(jiān)聽

public void actionPerformed(ActionEvent e) {

if (e.getSource() == but) {// 發(fā)送

if (bw == null) {

showTxt("當(dāng)前沒有客戶端連接,無法發(fā)送消息");

return;

}

String s = txt.getText().trim();// 得到文本框要發(fā)送的文字,去掉兩端空格

if (s.length() == 0) {

showTxt("不可以發(fā)送空消息");

return;

}

showTxt("我說:" + s);

try {

bw.write(s + "\n");// 發(fā)送網(wǎng)絡(luò)消息給對(duì)方

bw.flush();// 清空緩沖

} catch (IOException e1) {

showTxt("信息:" + s + " 發(fā)送失敗");

}

// 清空文本框,得到焦點(diǎn)

txt.setText("");

txt.requestFocus();

}

}

/**

* 連接服務(wù)器

*/

public void linkServer(){

showTxt("準(zhǔn)備連接服務(wù)器"+ip+":"+port);

try {

Socket jiaoYi = new Socket(ip,port);

showTxt("連接服務(wù)器成功,開始進(jìn)行通訊");

// 得到輸入和輸出

br = new BufferedReader(new InputStreamReader(

jiaoYi.getInputStream()));

bw = new BufferedWriter(new OutputStreamWriter(

jiaoYi.getOutputStream()));

String s = null;

while ((s = br.readLine()) != null) {

showTxt(s);

}

} catch (UnknownHostException e) {

showTxt("連接服務(wù)器失敗,網(wǎng)絡(luò)連通錯(cuò)誤");

} catch (IOException e) {

showTxt("與服務(wù)器通訊失敗,已經(jīng)斷開連接");

}

showTxt("關(guān)閉");

}

}

package service_client_for_many;

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.Vector;

/**

* 服務(wù)員,線程類

* 在客戶端連接后創(chuàng)建啟動(dòng)

* 負(fù)責(zé)當(dāng)前客戶端的所有數(shù)據(jù)收發(fā)

* 并且在業(yè)務(wù)需要時(shí),將結(jié)果與服務(wù)器(老板)進(jìn)行報(bào)告

*/

public class Waiter extends Thread{

private Socket sc;

private VectorWaiter dengJiBiao ;

private MutilServer server;

/**

* 客戶端IP

*/

private String ip;

private BufferedReader br;

private BufferedWriter bw;

/** 創(chuàng)建一個(gè)的新的服務(wù)員,負(fù)責(zé)當(dāng)前傳遞的客戶端連接(交易)

* 啟動(dòng)新線程

* @param sc 負(fù)責(zé)的交易

* @param dengJiBiao所有正在工作的服務(wù)員(所有交易)

* @param server 老板,也就是服務(wù)器

*/

public Waiter(Socket sc, VectorWaiter dengJiBiao,

MutilServer server) {

this.sc = sc;

this.dengJiBiao = dengJiBiao;

this.server = server;

//初始化連接的準(zhǔn)備工作

ip = sc.getInetAddress().getHostAddress();

// 得到輸入和輸出

try {

br = new BufferedReader(new InputStreamReader(

sc.getInputStream()));

bw = new BufferedWriter(new OutputStreamWriter(

sc.getOutputStream()));

} catch (IOException e) {

this.server.showTxt("與客戶端:"+ip+"建立通訊失敗");

e.printStackTrace();

return;//無效客戶,不再繼續(xù)

}

this.server.showTxt("客戶端:"+ip+"連接服務(wù)器成功");

//啟動(dòng)線程

this.start();

}

//線程

public void run(){

//開始時(shí),登記開工

dengJiBiao.addElement(this);

System.out.println(this.getClass().getName());

try {

String s = null;

while ((s = br.readLine()) != null) {

server.showTxt("客戶"+ip+"說:" + s);

//當(dāng)前客戶發(fā)來的信息,其它客戶也要能看得見.需要實(shí)現(xiàn)轉(zhuǎn)發(fā)

//從登記表找到所有正在干活的服務(wù)員

for (int i = 0; i dengJiBiao.size(); i++) {

Waiter w = dengJiBiao.get(i);

//排除掉當(dāng)前服務(wù)員自己

if(w!=this)

w.send("客戶"+ip+"說:" + s);

}

}

} catch (Exception e) {

server.showTxt("客戶"+ip+"已經(jīng)離開");

}

//結(jié)束時(shí),登記下班

dengJiBiao.removeElement(this);

}

/** 發(fā)送信息給當(dāng)前服務(wù)員負(fù)責(zé)的客戶端

* @param msg

*/

public void send(String msg){

try {

bw.write(msg+"\n");

bw.flush();

} catch (Exception e) {

server.showTxt("給客戶:"+ip+"發(fā)送信息"+msg+"失敗");

}

}

}

一個(gè)服務(wù)器類·兩個(gè)客戶端類,一個(gè)線程類負(fù)責(zé)收發(fā)

求java即時(shí)通訊的一個(gè)簡(jiǎn)單功能代碼

20分?。。???(⊙o⊙)

給你這個(gè)做參考吧。自己改一下就行了。(共兩個(gè)文件)

//ChatClient.java

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import java.net.*;

public class ChatClient extends Frame {

Socket s = null;

DataOutputStream dos = null;

DataInputStream dis = null;

private boolean bConnected = false;

TextField tfTxt = new TextField();

TextArea taContent = new TextArea();

Thread tRecv = new Thread(new RecvThread());

public static void main(String[] args) {

new ChatClient().launchFrame();

}

public void launchFrame() {

setLocation(400, 300);

this.setSize(300, 300);

add(tfTxt, BorderLayout.SOUTH);

add(taContent, BorderLayout.NORTH);

pack();

this.addWindowListener(new WindowAdapter() {

@Override

public void windowClosing(WindowEvent arg0) {

disconnect();

System.exit(0);

}

});

tfTxt.addActionListener(new TFListener());

setVisible(true);

connect();

tRecv.start();

}

public void connect() {

try {

s = new Socket("127.0.0.1", 8888);

dos = new DataOutputStream(s.getOutputStream());

dis = new DataInputStream(s.getInputStream());

System.out.println("connected!");

bConnected = true;

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

public void disconnect() {

try {

dos.close();

dis.close();

s.close();

} catch (IOException e) {

e.printStackTrace();

}

/*

try {

bConnected = false;

tRecv.join();

} catch(InterruptedException e) {

e.printStackTrace();

} finally {

try {

dos.close();

dis.close();

s.close();

} catch (IOException e) {

e.printStackTrace();

}

}

*/

}

private class TFListener implements ActionListener {

public void actionPerformed(ActionEvent e) {

String str = tfTxt.getText().trim();

//taContent.setText(str);

tfTxt.setText("");

try {

//System.out.println(s);

dos.writeUTF(str);

dos.flush();

//dos.close();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

private class RecvThread implements Runnable {

public void run() {

try {

while(bConnected) {

String str = dis.readUTF();

//System.out.println(str);

taContent.setText(taContent.getText() + str + '\n');

}

} catch (SocketException e) {

System.out.println("退出了,bye!");

} catch (EOFException e) {

System.out.println("推出了,bye - bye!");

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

//ChatServer.java

import java.io.*;

import java.net.*;

import java.util.*;

public class ChatServer {

boolean started = false;

ServerSocket ss = null;

ListClient clients = new ArrayListClient();

public static void main(String[] args) {

new ChatServer().start();

}

public void start() {

try {

ss = new ServerSocket(8888);

started = true;

} catch (BindException e) {

System.out.println("端口使用中....");

System.out.println("請(qǐng)關(guān)掉相關(guān)程序并重新運(yùn)行服務(wù)器!");

System.exit(0);

} catch (IOException e) {

e.printStackTrace();

}

try {

while(started) {

Socket s = ss.accept();

Client c = new Client(s);

System.out.println("a client connected!");

new Thread(c).start();

clients.add(c);

//dis.close();

}

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

ss.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

class Client implements Runnable {

private Socket s;

private DataInputStream dis = null;

private DataOutputStream dos = null;

private boolean bConnected = false;

public Client(Socket s) {

this.s = s;

try {

dis = new DataInputStream(s.getInputStream());

dos = new DataOutputStream(s.getOutputStream());

bConnected = true;

} catch (IOException e) {

e.printStackTrace();

}

}

public void send(String str) {

try {

dos.writeUTF(str);

} catch (IOException e) {

clients.remove(this);

System.out.println("對(duì)方退出了!我從List里面去掉了!");

//e.printStackTrace();

}

}

public void run() {

try {

while(bConnected) {

String str = dis.readUTF();

System.out.println(str);

for(int i=0; iclients.size(); i++) {

Client c = clients.get(i);

c.send(str);

//System.out.println(" a string send !");

}

/*

for(IteratorClient it = clients.iterator(); it.hasNext(); ) {

Client c = it.next();

c.send(str);

}

*/

/*

IteratorClient it = clients.iterator();

while(it.hasNext()) {

Client c = it.next();

c.send(str);

}

*/

}

} catch (EOFException e) {

System.out.println("Client closed!");

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

if(dis != null) dis.close();

if(dos != null) dos.close();

if(s != null) {

s.close();

//s = null;

}

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

}

}

如何寫一個(gè)即時(shí)通訊軟件?

網(wǎng)易云信致力于互聯(lián)網(wǎng)絡(luò)技術(shù)的開發(fā)與研究,使開發(fā)者通過簡(jiǎn)單集成客戶端SDK和云端開放API,快速實(shí)現(xiàn)強(qiáng)大的移動(dòng)互聯(lián)網(wǎng)IM和音視頻功能。在場(chǎng)景化方面,深入各行各業(yè),狠抓痛點(diǎn),第一時(shí)間包裝相應(yīng)的場(chǎng)景方案,助力企業(yè)解決行業(yè)難題。同時(shí),網(wǎng)易云信...

2020-03-09?回答者:網(wǎng)易(杭州)網(wǎng)絡(luò)有...?10

如何編寫一個(gè)即時(shí)通訊軟件

答:可以用bmob做后端,有即時(shí)通訊的demo 昨天下班前發(fā)布了最新的Bmob_IM_V1.1.2版本的SDK和應(yīng)用Demo,還未正式通知大家,但還是有人察覺到了,那么,這一次版本更新了什么呢? 主要是針對(duì)大家都比較關(guān)心的問題進(jìn)行了集中解決。 一、更新功能: 1、...

2016-12-21?回答者:?C900612?2個(gè)回答?1

如何搭建一個(gè)自己的IM即時(shí)通訊聊天軟件?

問:如何搭建一個(gè)自己的IM即時(shí)通訊聊天軟件?

答:搭建一個(gè)自己的IM即時(shí)通訊聊天軟件的框架如下:1、CIM 中的各個(gè)組件均采用 Spring Boot 構(gòu)建。2、采用 Netty + Google Protocol Buffer 構(gòu)建底層通信。3、Redis 存放各個(gè)客戶端的路由信息、賬號(hào)信息、在線狀態(tài)等。4、Zookeeper 用于 IM-server ...

2018-09-03?回答者:?容聯(lián)云??5個(gè)回答?1

怎么用Java寫一個(gè)即時(shí)通訊軟件?

答:我看到過一個(gè),鏈接給你,用websocket的 里面有個(gè)example就是im的

2013-05-24?回答者:?micoud_10?4個(gè)回答?1

寫一個(gè)簡(jiǎn)單的即時(shí)通訊軟件需要掌握哪些基礎(chǔ)的網(wǎng)絡(luò)知識(shí)

答:掌握TCP/UDP網(wǎng)絡(luò)協(xié)議,還要知道Socket知識(shí),會(huì)java或者C#或者C語言的編程,這樣就可以通過語言來實(shí)現(xiàn)網(wǎng)絡(luò)的通訊。建議看看Openfire,采用的協(xié)議是XMPP。

2017-02-16?回答者:?天123456941?1個(gè)回答

請(qǐng)問可以用哪些語言編寫即時(shí)通訊軟件?

問:并請(qǐng)說明那種語言最好

答:當(dāng)然要用JAVA和C++等多程序開發(fā). 你可以看這家企業(yè)即時(shí)通訊軟件

2007-03-14?回答者:?13813857798?3個(gè)回答

我要用java寫一個(gè)簡(jiǎn)單的即時(shí)通訊軟件,該怎么寫。...

問:我們打算先用http實(shí)現(xiàn)信息收發(fā),有人會(huì)做嗎。有demo的話求發(fā)我感謝。

答:你是說電腦端手機(jī)端都要開發(fā)嗎,電腦端一般用socket, Android端用XMPP5通信

2015-03-10?回答者:?淪落人1992?1個(gè)回答

自己寫的小型的即時(shí)通訊軟件如何像QQ一樣實(shí)現(xiàn)聊天...

答:用socket或者serversocket,也可以使用數(shù)據(jù)包。必須要有這個(gè),就可以在不同的計(jì)算機(jī)上實(shí)現(xiàn)即時(shí)通訊,但是,其功能與專業(yè)的聊天軟件差別比較大

2010-11-08?回答者:?孫7421?3個(gè)回答?5

求大神幫寫用JAVA編寫一個(gè)即時(shí)通信的軟件?有常 謝謝了

問:會(huì)的留言 可商量后再寫

答:描述得太不夠具體,,,,,是單對(duì)單、還是可以單對(duì)多;要不要分群;要不要圖片;等

2020-06-17?回答者:?知道網(wǎng)友?2個(gè)回答?1

開發(fā)一個(gè)即時(shí)通訊軟件需要什么樣的人員?

問:開發(fā)一個(gè)即時(shí)通訊軟件需要什么樣的人員?比如說需要幾個(gè)程序員,多少平面...

答:要看規(guī)模,不知道你要做多大的 架構(gòu)師 起碼1個(gè),如果大的話要兩個(gè) 數(shù)據(jù)庫設(shè)計(jì) 人員 美工1-2個(gè) 程序員依大小而定,小的話3,4個(gè) 大的話就每準(zhǔn)了 如果作為產(chǎn)品的話,時(shí)間將會(huì)很長(zhǎng),自己玩,自己用的話,就很快了


當(dāng)前文章:java即時(shí)通訊代碼的簡(jiǎn)單介紹
分享鏈接:http://fisionsoft.com.cn/article/dseijec.html