1. 程式人生 > >一個基於netty的websocket聊天demo

一個基於netty的websocket聊天demo

這裡,僅僅是一個demo,模擬客戶基於瀏覽器諮詢賣家問題的場景,但是,這裡的demo中,賣家不是人,是基於netty的程式(我就叫你uglyRobot吧),自動回覆了客戶問的問題。

專案特點如下:

1. 前端模擬在第三方應用中嵌入客戶諮詢頁面,這裡採用的是基於tornado的web應用,開啟頁面即進入諮詢視窗

2. 客戶諮詢的內容,將會原封不動的被uglyRobot作為答案返回。(真是情況下,客戶是不是會瘋掉,哈哈)

3. 客戶長時間不說話,uglyRobot會自動給予一段告知資訊,並將當前的channel釋放掉

4. 客戶再次回來問問題時,將不再顯示歡迎詞,重新分配channel進行"交流"

話不多說,直接上關鍵部分的程式碼。

首先,看前端的程式碼. python的web後臺部分:

複製程式碼
#!/usr/bin/env python
#-*- coding:utf-8 -*-
#__author__ "shihuc"

import tornado.ioloop
import tornado.httpserver
import tornado.web
import tornado.options
import os
import json
import multiprocessing

from tornado.options import define, options
define(
"port", default=9909, help="Please run on the given port", type=int) procPool = multiprocessing.Pool() class ChatHandler(tornado.web.RequestHandler): def get(self): self.render("chat.html") settings = { 'template_path': 'page', # html檔案 'static_path': 'resource', # 靜態檔案(css,js,img)
'static_url_prefix': '/resource/',# 靜態檔案字首 'cookie_secret': 'shihuc', # cookie自定義字串加鹽 'xsrf_cookies': True # 防止跨站偽造 } def make_app(): return tornado.web.Application([ (r"/", ChatHandler) ], default_host='',transforms=None, **settings) if __name__ == "__main__": tornado.options.parse_command_line() app = make_app() http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.current().start()
複製程式碼

聊天的前端html頁面的內容:

複製程式碼
<!DOCTYPE html>
<html>
<head lang="en">
    <link rel="shortcut icon" href="{{static_url('image/favicon.ico')}}" type="image/x-icon" />
    <!--<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />-->
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
    <title>瘋子聊天DEMO</title>
    <link rel="stylesheet" href="{{static_url('css/base.css')}}"/>
    <link rel="stylesheet" href="{{static_url('css/consult.css')}}"/>
</head>
<body>
    <div class="consultBox">
        <div class="consult">
            <div class="consult-Hd">
                <p class="checkmove"></p>
                <img src="{{static_url('image/backProperty.png')}}" alt=""/>
                <span>瘋子機器人有限公司</span>
                <a href="javascript:;" class="bell"></a>
                <a href="javascript:;" title="關閉" class="close"></a>
            </div>
            <div class="consult-Bd">
                <div class="consult-cont">
                    <div class="consult-cont-date"></div>
                </div>
            </div>
            <div class="consult-Fd">
                <div class="consult-Fd-hd">
                    <a href="javascript:;" class="brow"></a>
                    <a href="javascript:;" class="picture"></a>
                </div>
                <div>
                    <textarea class="consult-Fd-textarea" id="Ctextarea" autofocus spellcheck="false"></textarea>
                </div>
                <div class="buttonBox">
                    <span class="evaluate">請對服務做出評價</span>
                    <span class="button disable" id="Cbtn">傳送</span>
                </div>
            </div>
        </div>
    </div>
    <script src="{{static_url('js/jquery-1.11.1.min.js')}}"></script>
    <script src="{{static_url('js/bootstrap.min.js')}}"></script>
    <script src="{{static_url('js/bootbox.js')}}"></script>
    <script src="{{static_url('js/consult.js')}}"></script>
</body>
</html>
複製程式碼

重點前端邏輯consult.js的內容:

複製程式碼
  1 /**
  2  * Created by shihuc on 2017/2/21.
  3  */
  4 
  5 var ws = null;
  6 var wsurl = "ws://10.90.9.20:9080/websocket" 
  7 var wshandler = {};
  8 
  9     var consult={};
 10     consult.init=function(){
 11         consult.setDateInfo();
 12         consult.touch();
 13         consult.send();
 14     };
 15     consult.touch=function(){
 16         $('#Ctextarea').on('keyup',function(e){
 17             if(e.keyCode != 13){
 18                 if($('#Ctextarea').val()!=""){
 19                     $('.button').removeClass('disable');
 20                 }else{
 21                     $('.button').addClass('disable');
 22                 }
 23             }
 24         });
 25         $('.close').click(function(){
 26             $('.consultBox').addClass('hide');
 27         });
 28         $('.bell').click(function(){
 29             $(this).toggleClass('bell2');
 30         })
 31     };
 32     consult.send=function(){
 33         $('.button').click(function(){
 34             if(!$(this).hasClass('disable')){
 35                 var cont=$('#Ctextarea').val();
 36                 if(ws == null){
 37                    wshandler.reconnect(wshandler.interval, cont);
 38                 }else{
 39                    consult.fullSend(cont);
 40                 }
 41             }else{
 42                 return false;
 43             }
 44         });
 45         $('#Ctextarea').keydown(function(e){
 46             if(e.keyCode == 13){
 47                 if(!$('.button').hasClass('disable')){
 48                     var cont=$('#Ctextarea').val();
 49                     if(ws == null){
 50                         wshandler.reconnect(wshandler.interval, cont);
 51                     }else{
 52                         consult.fullSend(cont);
 53                     }
 54                 }else{
 55                     return false;
 56                 }
 57             }
 58         });
 59     };
 60     consult.fullSend = function(cont) {
 61         ws.send(cont);
 62         $('.consult-cont').append(consult.clientText(cont));
 63         $('#Ctextarea').val("");
 64         $('.button').addClass('disable');
 65         consult.position();
 66     };
 67     consult.clientText=function(cont){
 68         var newMsg= '<div class="consult-cont-right">';
 69         newMsg +='<div class="consult-cont-msg-wrapper">';
 70         newMsg +='<i class="consult-cont-corner"></i>';
 71         newMsg +='<div class="consult-cont-msg-container">';
 72         newMsg +="<p>Client: "+ cont +"</p>";
 73         newMsg +='</div>';
 74         newMsg +='</div>';
 75         newMsg +='</div>';
 76         return newMsg;
 77     };
 78     consult.serverText=function(cont){
 79         var newMsg= '<div class="consult-cont-left">';
 80         newMsg +='<div class="consult-cont-msg-wrapper">';
 81         newMsg +='<i class="consult-cont-corner"></i>';
 82         newMsg +='<div class="consult-cont-msg-container">';
 83         newMsg +="<p>"+ cont +"</p>";
 84         newMsg +='</div>';
 85         newMsg +='</div>';
 86         newMsg +='</div>';
 87         return newMsg;
 88     };
 89     consult.service = function(cont) {
 90         $('.consult-cont').append(consult.serverText(cont));
 91         consult.position();
 92     };
 93     consult.position=function(){
 94         var offset = $(".consult-Bd")[0].scrollHeight;
 95         $('.consult-Bd').scrollTop(offset);
 96     };
 97    consult.setDateInfo = function() {
 98        var dateInfo = new Date();
 99        console.log(dateInfo.toLocaleTimeString());
100        $('.consult-cont-date').text(dateInfo.toLocaleTimeString());
101    };
102 
103 /*
104  *下面是websocket操作相關的邏輯 by shihuc, 2017/3/9
105  */
106 wshandler.interval = 50;//unit is ms
107 wshandler.cycId = null;
108 wshandler.isFirst = true; //不是第一次的情況下,不顯示歡迎語
109 wshandler.connect = function() {  
110    if (ws != null) {  
111        console.log("現已連線");  
112        return ;  
113    }  
114    url = wsurl;  
115    if ('WebSocket' in window) {  
116        ws = new WebSocket(url);  
117    } else if ('MozWebSocket' in window) {  
118        ws = new MozWebSocket(url);  
119    } else {  
120        console.log("您的瀏覽器不支援WebSocket。");  
121        return ;  
122    }  
123    ws.onopen = function() {  
124        //設定發信息送型別為:ArrayBuffer  
125        ws.binaryType = "arraybuffer";  
126        //傳送一個字串和一個二進位制資訊  
127        if (wshandler.isFirst) {
128           ws.send("OPEN");  
129        }
130    }  
131    ws.onmessage = function(e) {  
132        consult.service(e.data.toString());
133    }  
134    ws.onclose = function(e) {  
135        console.log("onclose: closed");
136        wshandler.disconnect(); 
137        wshandler.isFirst = false;
138    }  
139    ws.onerror = function(e) {  
140        console.log("onerror: error");  
141        wshandler.disconnect();
142        wshandler.isFirst = false;
143    }  
144 }  
145 
146 function checkOpenState(interval,cont) {
147    if (ws.readyState == ws.OPEN){
148        consult.fullSend(cont);
149        clearInterval(wshandler.cycId);
150    }else{
151        console.log("Wait for ws to be open again");
152        wshandler.cycId = setInterval("checkOpenState(" + interval + "," + cont + ")", interval);
153    }
154 }
155 
156 wshandler.reconnect = function(interval, cont) {
157    wshandler.connect();
158    var newCont = "\'" + cont + "\'";
159    checkOpenState(interval, newCont);
160 }
161 
162 //斷開連線  
163 wshandler.disconnect = function() {  
164    if (ws != null) {  
165        ws.close();  
166        ws = null;          
167    }  

            
           

相關推薦

5分鐘搭建一個HTML5視訊聊天Demo(WebRTC+NodeJS)

轉載自: http://blog.csdn.net/u012377333/article/category/2670379   謝謝版主 到 http://nodejs.org/ 下載最新版nodejs,我下的是“node-v0.10.7-x86.msi”。 安裝,

一個基於netty的websocket聊天demo

這裡,僅僅是一個demo,模擬客戶基於瀏覽器諮詢賣家問題的場景,但是,這裡的demo中,賣家不是人,是基於netty的程式(我就叫你uglyRobot吧),自動回覆了客戶問的問題。 專案特點如下: 1. 前端模擬在第三方應用中嵌入客戶諮詢頁面,這裡採用的是基於torn

用SpringBoot整合Netty開發一個基於WebSocket的聊天

前言 基於SpringBoot,藉助Netty控制長連結,使用WebSocket協議做一個實時的聊天室。 專案效果 專案統一登入路徑: http://localhost:8080/chat/netty 使用者名稱隨機生成,離線呼叫非同步方法,資料寫操作,登入顯示歷史聊天

基於node.js打造一個簡易的聊天

1.先寫服務端的程式碼 在服務端要先進行安裝node環境,然後用npm install socket.io 要安裝express框架 let http = require('http'); let fs = require('fs'); let ws = require('socket.

一個基於webSocket實現前後端通訊的小demo

#sell 一般的web專案都是前臺向後臺傳送訊息,但是有些時候我們也需要從後端向前臺傳送訊息,比如說zfb的回撥資訊,微信的模板推送訊息等,下面通過Eclipse+Tomcat實現一個前後臺通訊的小demo; 先建立一個web專案  index.jsp寫一個簡單的頁面來

開發一個基於React Native的簡易demo--視訊元件+佈局

一、視訊元件 yarn add --save react-native-video react-native link 編碼 import Video from 'react-native-video'; ... <Video r

一個基於智慧問答的聊天機器人實現

 智慧問答應當是未來智慧化發展中人機互動的主要方式,目前無論是在開源社群或者企業應用中,都有廣泛的應用。      專案名稱是Iveely.Brain,本次原始碼可以在Github的這裡下載,,是主要用於聊天服務的一個專案,本次開源版本的示例如下所示:        

一個基於ES6+webpack的vue小demo

上一篇文章《一個基於ES5的vue小demo》我們講了如何用ES5,vue-router做一個小demo,接下來我們來把它變成基於ES6+webpack的demo。 一、環境搭建及程式碼轉換 我們先搭建一下vue 的開發環境,根據我的一篇隨筆《Vue開發環境搭建及熱更新》,

基於Node.js + socket.io實現WebSocket的聊天DEMO

原文摘自我的前端部落格,歡迎大家來訪問 簡介 最近看Node.js和HTML5,練手了一個簡易版的聊天DEMO,娛樂一下 為什麼需要socket.io? node.js提供了高效的服務端執行環境,但是由於瀏覽器端對HTML5的支援不一, 為了相容所有瀏覽器,提供卓越

linux系統下一個基於TCP的網路聊天

本聊天室程式在Ubuntu下,採用C語言實現,結構為Client/Server結構; 服務端程式通過共享儲存區儲存聊天資料,併發送給每個連線的客戶端; 服務端程式和客戶端程式都是通過父子程序分別負責傳送和接收資料的,以避免資料衝撞; 需按以下格式呼叫客戶端程式:client

一個基於ES6 的Mvvm Demo

很多次面試都被問到雙向繫結的原理,從一開始的啥都不知道到後來知道使用Object.defineProperty 劫持屬性,使用釋出訂閱進行訊息傳遞,再後來看了很多篇相關的文章和程式碼,依然應付不了面試官的追問。還是對其中的原理和實現瞭解的不透徹,所以最終決定自己親手寫一個。網

C 基於UDP實現一個簡易的聊天

引言 本文是圍繞Linux udp api 構建一個簡易的多人聊天室.重點看思路,幫助我們加深 對udp開發中一些api瞭解.相對而言udp socket開發相比tcp socket開發注意的細節要少很多. 但是水也很深. 本文就當是一個demo整合幫助開發者回顧和繼續瞭解

在Ubuntu上部署一個基於webrtc的多人視訊聊天服務

最近研究webrtc視訊直播技術,網上找了些教程最終都不太能順利跑起來的,可能是文章寫的比較老,使用的一些開源元件已經更新了,有些配置已經不太一樣了,所以按照以前的步驟會有問題。折騰了一陣終於跑起來了,記錄一下。 一個簡單的聊天室html頁面 這個頁面使用simple-webrtc來實現webrtc的通訊,s

pyDash:一個基於 web 的 Linux 性能監測工具

亮顯 依賴關系 stat 運行 tld 下一個 google avi 查看 pyDash 是一個輕量且基於 web 的 Linux 性能監測工具,它是用 Python 和 Django 加上 Chart.js 來寫的。經測試,在下面這些主流 Linux 發行版上可運行:Ce

一個基於QT簡單登錄對話框(帶驗證碼功能)

oid mov rim cat pla .sh end qpainter turn 1. 對話框樣式 2. 源代碼 ①. main.cpp #include <QtGui/QApplication> #include "QLoginDialog.h

jQuery EasyUI一個基於 jQuery 的框架(創建網頁所需的一切)

fault def edi lec ... center icon jquer timeout jQuery EasyUI學習網址:http://www.runoob.com/jeasyui/jqueryeasyui-tutorial.html jQuery MiniUI

聊聊高並發(三十二)實現一個基於鏈表的無鎖Set集合

target 方向 刪除 元素 min 集合 date 變量 find Set表示一種沒有反復元素的集合類,在JDK裏面有HashSet的實現,底層是基於HashMap來實現的。這裏實現一個簡化版本號的Set,有下面約束: 1. 基於鏈表實現。鏈表節點依照對象的h

Spring Boot入門第二天:一個基於Spring Boot的Web應用,使用了Spring Data JPA和Freemarker。

per pan let mysq 應用 posit ble host thead 今天打算從數據庫中取數據,並展示到視圖中。不多說,先上圖: 第一步:添加依賴。打開pom.xml文件,添加必要的依賴,完整代碼如下: <?xml version="1.0" enco

傳智:自己簡單實現一個struts2框架的demo

throws for request 運行 本地化 color ray run main struts2的結構圖: 代碼實現: 組織結構: 主要代碼: package cn.itcast.config; import org.apache.log4j.Logg

如何利用Facebook的create-react-app腳手架創建一個基於ant design mobile的項目

https dev one 解決方案 edas mdm and tro 輸入 引言:   create-react-app是Facebook發布的一款全局的命令行工具用來創建一個新的項目。   通常我們開始做一個react web或者 app 項目的時候,都會自己