原理
成都創(chuàng)新互聯(lián)公司,為您提供網(wǎng)站建設(shè)公司、成都網(wǎng)站制作、網(wǎng)站營銷推廣、網(wǎng)站開發(fā)設(shè)計,對服務PE包裝袋等多個行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗。成都創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司成立于2013年,提供專業(yè)網(wǎng)站制作報價服務,我們深知市場的競爭激烈,認真對待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進步,是我們永遠的責任!
WebSocket protocol 。
現(xiàn)很多網(wǎng)站為了實現(xiàn)即時通訊,所用的技術(shù)都是輪詢(polling)。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發(fā)出HTTP request,然后由服務器返回最新的數(shù)據(jù)給客戶端的瀏覽器。這種傳統(tǒng)的HTTP request 的模式帶來很明顯的缺點 – 瀏覽器需要不斷的向服務器發(fā)出請求,然而HTTP request 的header是非常長的,里面包含的有用數(shù)據(jù)可能只是一個很小的值,這樣會占用很多的帶寬。
而比較新的技術(shù)去做輪詢的效果是Comet – 用了AJAX。但這種技術(shù)雖然可達到全雙工通信,但依然需要發(fā)出請求。
在 WebSocket API,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。在此WebSocket 協(xié)議中,為我們實現(xiàn)即時服務帶來了兩大好處:
1. Header
互相溝通的Header是很小的-大概只有 2 Bytes
2. Server Push
服務器的推送,服務器不再被動的接收到瀏覽器的request之后才返回數(shù)據(jù),而是在有新數(shù)據(jù)時就主動推送給瀏覽器。
一、項目簡介
WebSocket是HTML5一種新的協(xié)議,它實現(xiàn)了瀏覽器與服務器全雙工通信,這里就將使用WebSocket來開發(fā)網(wǎng)頁聊天室,前端框架會使用AmazeUI,后臺使用Java,編輯器使用UMEditor。
二、涉及知識點
網(wǎng)頁前端(HTML+CSS+JS)和Java
三、軟件環(huán)境 Tomcat 7 JDK 7 Eclipse JavaEE 現(xiàn)代瀏覽器
四、效果截圖
效果1
效果2
五、項目實戰(zhàn)
1. 新建項目
打開Eclipse JavaEE,新建一個名為Chat的Dynamic Web Project,然后導入處理JSON格式字符串所需要的包,把commons-beanutils-1.8.0.jar、commons-collections-3.2.1.jar、commons-lang-2.5.jar、commons-logging-1.1.1.jar、ezmorph-1.0.6.jar和json-lib-2.4-jdk15.jar這幾個包放在WebContent/WEB-INF/lib目錄下,最后把項目發(fā)布到Tomcat服務器上,到此空項目就搭建完成了。
2. 編寫前端頁面
在WebContent目錄下新建一個名為index.jsp的頁面,這里使用了AmazeUI框架,它是一個跨屏自適應的前端框架,消息輸入框使用了UMEditor,它是一個富文本在線編輯器,能讓我們的消息內(nèi)容多姿多彩。
首先從 AmazeUI官網(wǎng) 下載壓縮包,然后解壓把assets文件夾拷貝到WebContent目錄下,這樣我們就能使用AmazeUI了。
再從 UEditer官網(wǎng) 下載Mini版的JSP版本壓縮包,解壓后把整個目錄拷貝到WebContent目錄下,接下來就可以編寫前端代碼了,代碼如下(你可以按照自己的喜好編寫):
?
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 ? ?%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%!DOCTYPE htmlhtml lang="zh"headmeta charset="utf-8"meta http-equiv="X-UA-Compatible" content="IE=edge"meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"titleShiYanLou Chat/title!-- Set render engine for 360 browser --meta name="renderer" content="webkit"!-- No Baidu Siteapp--meta http-equiv="Cache-Control" content="no-siteapp" /link rel="alternate icon" href="assets/i/favicon.ico"link rel="stylesheet" href="assets/css/amazeui.min.css"link rel="stylesheet" href="assets/css/app.css"!-- umeditor css --link href="umeditor/themes/default/css/umeditor.css" rel="stylesheet"style.title {?text-align: center;}.chat-content-container {?height: 29rem;?overflow-y: scroll;?border: 1px solid silver;}/style/headbody?!-- title start --?div class="title"??div class="am-g am-g-fixed"???div class="am-u-sm-12"????h1 class="am-text-primary"ShiYanLou Chat/h1???/div??/div?/div?!-- title end --?!-- chat content start --?div class="chat-content"??div class="am-g am-g-fixed chat-content-container"???div class="am-u-sm-12"????ul id="message-list" class="am-comments-list am-comments-list-flip"/ul???/div??/div?/div?!-- chat content start --?!-- message input start --?div class="message-input am-margin-top"??div class="am-g am-g-fixed"???div class="am-u-sm-12"????form class="am-form"?????div class="am-form-group"??????script type="text/plain" id="myEditor" style="width: 100%;height: 8rem;"/script?????/div????/form???/div??/div??div class="am-g am-g-fixed am-margin-top"???div class="am-u-sm-6"????div id="message-input-nickname" class="am-input-group am-input-group-primary"?????span class="am-input-group-label"i class="am-icon-user"/i/span?????input id="nickname" type="text" class="am-form-field" placeholder="Please enter nickname"/????/div???/div???div class="am-u-sm-6"????button id="send" type="button" class="am-btn am-btn-primary"?????i class="am-icon-send"/i Send????/button???/div??/div?/div?!-- message input end --?!--[if (gte IE 9)|!(IE)]!--?script src="assets/js/jquery.min.js"/script?!--![endif]--?!--[if lte IE 8 ]?script src=""/script?![endif]--?!-- umeditor js --?script charset="utf-8" src="umeditor/umeditor.config.js"/script?script charset="utf-8" src="umeditor/umeditor.min.js"/script?script src="umeditor/lang/zh-cn/zh-cn.js"/script?script??$(function() {???// 初始化消息輸入框???var um = UM.getEditor('myEditor');???// 使昵稱框獲取焦點???$('#nickname')[0].focus();??});?/script/body/html ?
編寫完成之后啟動Tomcat服務器,然后訪問 ? ,會看到如下界面。
3. 編寫后臺代碼
新建一個com.shiyanlou.chat的包,在包中創(chuàng)建一個名為ChatServer的類,從JavaEE 7開始就統(tǒng)一了WebSocket的API,因此無論是什么服務器,用Java寫的代碼都是一樣的,代碼如下:
?
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 ? ?package com.shiyanlou.chat;import java.text.SimpleDateFormat;import java.util.Date;import javax.websocket.OnClose;import javax.websocket.OnError;import javax.websocket.OnMessage;import javax.websocket.OnOpen;import javax.websocket.Session;import javax.websocket.server.ServerEndpoint;import net.sf.json.JSONObject;/**?* 聊天服務器類?* @author shiyanlou?*?*/@ServerEndpoint("/websocket")public class ChatServer {?private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");? // 日期格式化?@OnOpen?public void open(Session session) {??// 添加初始化操作?}?/**??* 接受客戶端的消息,并把消息發(fā)送給所有連接的會話??* @param message 客戶端發(fā)來的消息??* @param session 客戶端的會話??*/?@OnMessage?public void getMessage(String message, Session session) {??// 把客戶端的消息解析為JSON對象??JSONObject jsonObject = JSONObject.fromObject(message);??// 在消息中添加發(fā)送日期??jsonObject.put("date", DATE_FORMAT.format(new Date()));??// 把消息發(fā)送給所有連接的會話??for (Session openSession : session.getOpenSessions()) {???// 添加本條消息是否為當前會話本身發(fā)的標志???jsonObject.put("isSelf", openSession.equals(session));???// 發(fā)送JSON格式的消息???openSession.getAsyncRemote().sendText(jsonObject.toString());??}?}?@OnClose?public void close() {??// 添加關(guān)閉會話時的操作?}?@OnError?public void error(Throwable t) {??// 添加處理錯誤的操作?}} ?
4. 前后臺交互
后臺寫完了,前臺要用WebSocket連接后臺,需要新建一個WebSocket對象,然后就可以和服務器端進行交互,從瀏覽器發(fā)送消息給服務器端,同時要驗證輸入框的內(nèi)容是否為空,然后接受服務端發(fā)送的消息,把它們動態(tài)地添加到聊天內(nèi)容框中,在
?
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 ? ?var um = UM.getEditor('myEditor');$('#nickname')[0].focus();// 新建WebSocket對象,最后的/websocket對應服務器端的@ServerEndpoint("/websocket")var socket = new WebSocket('ws://${pageContext.request.getServerName()}:${pageContext.request.getServerPort()}${pageContext.request.contextPath}/websocket');???// 處理服務器端發(fā)送的數(shù)據(jù)???socket.onmessage = function(event) {????addMessage(event.data);???};???// 點擊Send按鈕時的操作???$('#send').on('click', function() {????var nickname = $('#nickname').val();????if (!um.hasContents()) {??? // 判斷消息輸入框是否為空?????// 消息輸入框獲取焦點?????um.focus();?????// 添加抖動效果?????$('.edui-container').addClass('am-animation-shake');?????setTimeout("$('.edui-container').removeClass('am-animation-shake')", 1000);????} else if (nickname == '') {??? // 判斷昵稱框是否為空?????//昵稱框獲取焦點?????$('#nickname')[0].focus();?????// 添加抖動效果?????$('#message-input-nickname').addClass('am-animation-shake');?????setTimeout("$('#message-input-nickname').removeClass('am-animation-shake')", 1000);????} else {?????// 發(fā)送消息?????socket.send(JSON.stringify({??????content : um.getContent(),??????nickname : nickname?????}));?????// 清空消息輸入框?????um.setContent('');?????// 消息輸入框獲取焦點?????um.focus();????}???});???// 把消息添加到聊天內(nèi)容中???function addMessage(message) {????message = JSON.parse(message);????var messageItem = 'li class="am-comment '??????+ (message.isSelf ? 'am-comment-flip' : 'am-comment')??????+ '"'??????+ 'a href="javascript:void(0)" img src="assets/images/'??????+ (message.isSelf ? 'self.png' : 'others.jpg')??????+ '" alt="" width="48" height="48"http://a'??????+ 'divheaderdiv'??????+ 'a href="javascript:void(0)"'??????+ message.nickname + '/a time' + message.date??????+ '/time/div/header'??????+ 'div' + message.content??????+ '/div/div/li';????$(messageItem).appendTo('#message-list');????// 把滾動條滾動到底部????$(".chat-content-container").scrollTop($(".chat-content-container")[0].scrollHeight);???} ?
到這步,簡單的網(wǎng)頁聊天室就完成了,你可以多開幾個窗口或在局域網(wǎng)中邀請小伙伴們來一起測試。
六、小結(jié)
本次項目課使用WebSocket實現(xiàn)了簡單的網(wǎng)頁聊天室,其實WebSocket不僅可以應用于瀏覽器,也可以應用于桌面客戶端。
/**
* 基于UDP協(xié)議的聊天程序
*
* 2007.9.18
* */
//導入包
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.net.*;
public class Chat extends JFrame implements ActionListener
{
//廣播地址或者對方的地址
public static final String sendIP = "172.18.8.255";
//發(fā)送端口9527
public static final int sendPort = 9527;
JPanel p = new JPanel();
List lst = new List(); //消息顯示
JTextField txtIP = new JTextField(18); //填寫IP地址
JTextField txtMSG = new JTextField(20); //填寫發(fā)送消息
JLabel lblIP = new JLabel("IP地址:");
JLabel lblMSG = new JLabel("消息:");
JButton btnSend = new JButton("發(fā)送");
byte [] buf;
//定義DatagramSocket的對象必須進行異常處理
//發(fā)送和接收數(shù)據(jù)報包的套接字
DatagramSocket ds = null;
//=============構(gòu)造函數(shù)=====================
public Chat()
{
CreateInterFace();
//注冊消息框監(jiān)聽器
txtMSG.addActionListener(this);
btnSend.addActionListener(this);
try
{
//端口:9527
ds =new DatagramSocket(sendPort);
}
catch(Exception ex)
{
ex.printStackTrace();
}
//============接受消息============
//匿名類
new Thread(new Runnable()
{
public void run()
{
byte buf[] = new byte[1024];
//表示接受數(shù)據(jù)報包
while(true)
{
try
{
DatagramPacket dp = new DatagramPacket(buf,1024,InetAddress.getByName(txtIP.getText()),sendPort);
ds.receive(dp);
lst.add("【消息來自】◆" + dp.getAddress().getHostAddress() + "◆"+"【說】:" + new String (buf,0,dp.getLength()) /*+ dp.getPort()*/,0);
}
catch(Exception e)
{
if(ds.isClosed())
{
e.printStackTrace();
}
}
}
}
}).start();
//關(guān)閉窗體事件
this.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent w)
{
System.out.println("test");
int n=JOptionPane.showConfirmDialog(null,"是否要退出?","退出",JOptionPane.YES_NO_OPTION);
if(n==JOptionPane.YES_OPTION)
{
dispose();
System.exit(0);
ds.close();//關(guān)閉ds對象//關(guān)閉數(shù)據(jù)報套接字
}
}
});
}
//界面設(shè)計布局
public void CreateInterFace()
{
this.add(lst,BorderLayout.CENTER);
this.add(p,BorderLayout.SOUTH);
p.add(lblIP);
p.add(txtIP);
p.add(lblMSG);
p.add(txtMSG);
p.add(btnSend);
txtIP.setText(sendIP);
//背景顏色
lst.setBackground(Color.yellow);
//JAVA默認風格
this.setUndecorated(true);
this.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
this.setSize(600,500);
this.setTitle("〓聊天室〓");
this.setResizable(false);//不能改變窗體大小
this.setLocationRelativeTo(null);//窗體居中
this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.setVisible(true);
txtMSG.requestFocus();//消息框得到焦點
}
//===============================Main函數(shù)===============================
public static void main(String[]args)
{
new Chat();
}
//================================發(fā)送消息===============================
//消息框回車發(fā)送消息事件
public void actionPerformed(ActionEvent e)
{
//得到文本內(nèi)容
buf = txtMSG.getText().getBytes();
//判斷消息框是否為空
if (txtMSG.getText().length()==0)
{
JOptionPane.showMessageDialog(null,"發(fā)送消息不能為空","提示",JOptionPane.WARNING_MESSAGE);
}
else{
try
{
InetAddress address = InetAddress.getByName(sendIP);
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName(txtIP.getText()),sendPort);
ds.send(dp);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
txtMSG.setText("");//清空消息框
//點發(fā)送按鈕發(fā)送消息事件
if(e.getSource()==btnSend)
{
buf = txtMSG.getText().getBytes();
try
{
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName(txtIP.getText()),sendPort);
}
catch(Exception ex)
{
ex.printStackTrace();
}
txtMSG.setText("");//清空消息框
txtMSG.requestFocus();
}
}
}
主要有這么幾個頁面:1.注冊 2.登陸 3.房間選擇和聊天頁面 。用戶先到1頁面注冊賬號,然后到2登陸聊天室,再到3頁面加入一個已經(jīng)創(chuàng)建的房間,開始聊天。具體做就麻煩了,我以前做這個玩意花了2天。有個技術(shù)難點要克服,A在他的聊天頁面上說了一句話,B的聊天頁面必須立刻把這句話顯示出來??梢赃@么做,A說話了,他點了提交按鈕,那么一個請求被提交到后臺的servlet或者action,后臺知道A說了一句話,于是,把全局變量(例如application里)messageArrived的值設(shè)置為true,聊天頁面有段JavaScript代碼,每隔一小段時間(如0.2秒)檢查messageArrived的值,發(fā)現(xiàn)messageArrived==true,就刷新頁面(頁面刷新時,A說的話就顯示出來了),然后再把messageArrived設(shè)回false。這樣聊天記錄能實時地顯示。因為每個人說話,都會導致整個頁面刷新,所以這個聊天室給人的感覺是,頁面一卡一卡的,不正常。ajax用上以后,不會有整個頁面老刷新的現(xiàn)象了,給用戶的感覺很好。
網(wǎng)頁標題:java代碼網(wǎng)頁聊天 java實現(xiàn)網(wǎng)頁聊天
本文路徑:http://jinyejixie.com/article36/dossipg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機、定制開發(fā)、微信公眾號、服務器托管、ChatGPT、網(wǎng)頁設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)