WebSocket 和 Golang 实现聊天功能
http://www.open-open.com/lib/view/open1416379948711.html
这个示例应用程序展示了如何使用 WebSocket, Golang 和 jQuery 创建一个简单的web聊天应用程序。这个示例的源代码在 https://github.com/waylau/goChat 。
Running the example 运行示例
这个示例需要 Golang 开发环境。 该页面描述如何安装开发环境。
一旦你去启动和运行,您可以下载、构建和运行的例子, 使用命令:
go get gary.burd.info/go-websocket-chat
go-websocket-chat
在支持 websocket 的浏览器尝试打开 http://127.0.0.1:8080/ 启动应用
Server 服务器
服务器程序实现了 http 包,包含了 Go 分发和 Gorilla 项目的 websocket 包.
应用程序定义了两种类型, connection 和 hub 。服务器为每个 webscocket 连接 创建的一个 connection 类型的实例 。 连接器扮演了 websocket 和 hub 类型单例 之间的媒介 。 hub 保持一组注册了的连接器 和 广播到连接器的信息。
程序运行了一个 goroutine 给 hub 和两个 goroutine 给每个连接器。 goroutine 通过 channel 和其他进行交流。 hub 拥有注册连接器、注销连接器和广播信息的 channel。一个连机器拥有缓存的发出信息的 channel 。其中一个 连接器的 goroutine 从这个 channel 中读信息 并把信息写入 webscoket。另外一个连接器 goroutine 从 websocket 读信息,并把信息发送到 hub。
下面是 hub 类型代码:
package main
type hub struct {
// 注册了的连接器
connections map[*connection]bool
// 从连接器中发入的信息
broadcast chan []byte
// 从连接器中注册请求
register chan *connection
// 从连接器中注销请求
unregister chan *connection
}
var h = hub{
broadcast: make(chan []byte),
register: make(chan *connection),
unregister: make(chan *connection),
connections: make(map[*connection]bool),
}
func (h *hub) run() {
for {
select {
case c := <-h.register:
h.connections[c] = true
case c := <-h.unregister:
if _, ok := h.connections[c]; ok {
delete(h.connections, c)
close(c.send)
}
case m := <-h.broadcast:
for c := range h.connections {
select {
case c.send <- m:
default:
delete(h.connections, c)
close(c.send)
}
}
}
}
}
应用程序的 主要 函数启动 hub 以 goroutine 形式运行方法。连接器 发送请求到 hub 通过 注册、注销和广播 channel。
hub 注册连接器通过添加 connection 的指针作为 connections map 的主键。这个 map 的值通常是 true。
注销的代码有点复杂。除了从 connections map 删除连接器的指针外, hub 关闭了 connection 的发送,来标识没有信息再被发送到 connection了。
hub 通过循环注册连接器和发送信息到连接器的发送 channel 来控制信息。 如果连接器的发送缓冲区已经满了,那么 hub 假设 客户端已死或卡住了。这种情况下, hub 注销连接器 并关闭 websocket.
下面关于 connection 类型的代码:
package main import (
"github.com/gorilla/websocket"
"net/http"
) type connection struct {
// websocket 连接器
ws *websocket.Conn // 发送信息的缓冲 channel
send chan []byte
} func (c *connection) reader() {
for {
_, message, err := c.ws.ReadMessage()
if err != nil {
break
}
h.broadcast <- message
}
c.ws.Close()
} func (c *connection) writer() {
for message := range c.send {
err := c.ws.WriteMessage(websocket.TextMessage, message)
if err != nil {
break
}
}
c.ws.Close()
} var upgrader = &websocket.Upgrader{ReadBufferSize: 1024, WriteBufferSize: 1024} func wsHandler(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
return
}
c := &connection{send: make(chan []byte, 256), ws: ws}
h.register <- c
defer func() { h.unregister <- c }()
go c.writer()
c.reader()
}
wsHandler 方法被主函数当做http handler注册。HTTP 连接到 WebSocket 协议的升级,创建一个连接对象,注册这个连接到 sub ,并通过 defer延迟语句 来控制 连接的注销。
接着,wsHandler 方法开启 连接器的写入方法作为一个 goroutine。 写入方法将信息从连接器的 channel 转入 websocket。当 hub 关闭 channel 或者 在写入 websocket 时出错,写入方法关闭。
最后,wsHandler 方法 调用连接器的 读 方法。 读方法将 入站消息 从 websocket 转到 hub。
这里是服务器的代码的其余部分:
package main import (
"flag"
"go/build"
"log"
"net/http"
"path/filepath"
"text/template"
) var (
addr = flag.String("addr", ":8080", "http service address")
assets = flag.String("assets", defaultAssetPath(), "path to assets")
homeTempl *template.Template
) func defaultAssetPath() string {
p, err := build.Default.Import("gary.burd.info/go-websocket-chat", "", build.FindOnly)
if err != nil {
return "."
}
return p.Dir
} func homeHandler(c http.ResponseWriter, req *http.Request) {
homeTempl.Execute(c, req.Host)
} func main() {
flag.Parse()
homeTempl = template.Must(template.ParseFiles(filepath.Join(*assets, "home.html")))
go h.run()
http.HandleFunc("/", homeHandler)
http.HandleFunc("/ws", wsHandler)
if err := http.ListenAndServe(*addr, nil); err != nil {
log.Fatal("ListenAndServe:", err)
}
}
应用主程序启动 hub goroutine。 接着 主程序 注册 主页 和 websocket 连接器的控制器N。最后主程序启动 HTTP 服务器。
Client 客户端
客户端的实现是一个简单的 HTML 文件:
<html>
<head>
<title>Chat Example</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() { var conn;
var msg = $("#msg");
var log = $("#log"); function appendLog(msg) {
var d = log[0]
var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight;
msg.appendTo(log)
if (doScroll) {
d.scrollTop = d.scrollHeight - d.clientHeight;
}
} $("#form").submit(function() {
if (!conn) {
return false;
}
if (!msg.val()) {
return false;
}
conn.send(msg.val());
msg.val("");
return false
}); if (window["WebSocket"]) {
conn = new WebSocket("ws://{{$}}/ws");
conn.onclose = function(evt) {
appendLog($("<div><b>Connection closed.</b></div>"))
}
conn.onmessage = function(evt) {
appendLog($("<div/>").text(evt.data))
}
} else {
appendLog($("<div><b>Your browser does not support WebSockets.</b></div>"))
}
});
</script>
<style type="text/css">
html {
overflow: hidden;
} body {
overflow: hidden;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
background: gray;
} #log {
background: white;
margin: 0;
padding: 0.5em 0.5em 0.5em 0.5em;
position: absolute;
top: 0.5em;
left: 0.5em;
right: 0.5em;
bottom: 3em;
overflow: auto;
} #form {
padding: 0 0.5em 0 0.5em;
margin: 0;
position: absolute;
bottom: 1em;
left: 0px;
width: 100%;
overflow: hidden;
} </style>
</head>
<body>
<div id="log"></div>
<form id="form">
<input type="submit" value="Send" />
<input type="text" id="msg" size="64"/>
</form>
</body>
</html>
客户端使用 jQuery
文档加载。脚本检查 websocket 的功能 。如果 WebSocket 功能 可以用,然后打开脚本与服务器的连接,并注册一个回调处理来自服务器的信息。回调使用 appendlog 方法将消息添加到聊天记录。
appendlog 方法检查在添加新的内容时的滚动位置,从而可以让用户手动滚动聊天记录而不会被新来的消息中断。如果聊天记录滚动至底部,那么新内容添加的到旧内容的后面。否则,滚动的位置不会改变。
表单处理器将用户的输入写入到 WebSocket 并且清除输入字段。
参考:http://gary.burd.info/go-websocket-chat
来自:http://www.waylau.com/go-websocket-chat/
WebSocket 和 Golang 实现聊天功能的更多相关文章
- WebSocket(3)---实现一对一聊天功能
实现一对一聊天功能 功能介绍:实现A和B单独聊天功能,即A发消息给B只能B接收,同样B向A发消息只能A接收. 本篇博客是在上一遍基础上搭建,上一篇博客地址:[WebSocket]---实现游戏公告功能 ...
- Spring Websocket实现简易在线聊天功能
针对Spring Websocket的实现,我参照了其他博主的文章https://www.cnblogs.com/leechenxiang/p/5306372.html 下面直接给出实现: 一.引入相 ...
- webSocket实现多人聊天功能
webSocket实现多人在线聊天 主要思路如下: 1.使用vue构建简单的聊天室界面 2.基于nodeJs 的webSocket开启一个socket后台服务,前端使用H5的webSocket来创建一 ...
- Spring 学习——基于Spring WebSocket 和STOMP实现简单的聊天功能
本篇主要讲解如何使用Spring websocket 和STOMP搭建一个简单的聊天功能项目,里面使用到的技术,如websocket和STOMP等会简单介绍,不会太深,如果对相关介绍不是很了解的,请自 ...
- 使用websocket实现在线聊天功能
很早以前为了快速达到效果,使用轮询实现了在线聊天功能,后来无意接触了socket,关于socket我的理解是进程间通信,首先要有服务器跟客户端,服务的启动监听某ip端口定位该进程,客户端开启socke ...
- spring boot集成websocket实现聊天功能和监控功能
本文参考了这位兄台的文章: https://blog.csdn.net/ffj0721/article/details/82630134 项目源码url: https://github.com/zhz ...
- 基于vs2015 SignalR开发的微信小程序使用websocket实现聊天功能
一)前言 在微信小程上实现聊天功能,大致有三种方式:1)小程序云开发 2)购买第三方IM服务 3)使用自己的服务器自己开发. 这里重要讲使用自己的服务器自己开发,并且是基于vs的开发. 网上提供的解决 ...
- JAVA结合WebSocket实现简单客服聊天功能
说明:该示例只简单的实现了客服聊天功能. 1.聊天记录没有保存到数据库中,一旦服务重启,消息记录将会没有,如果需要保存到数据库中,可以扩展 2.页面样式用的网上模板,样式可以自己进行修改 3.只能由用 ...
- 【WebSocket No.2】WebSocket和Socket实现聊天群发
介绍: 前面写过一篇简单的websocke实现服务端.这一篇就不在说什么基础的东西主要是来用实例说话,主要是讲一下实现单聊和群组聊天和所有群发的思路设计. 直接不懂的可以看一下上一篇简单版本再来看也行 ...
随机推荐
- (Tomcat)服务器之web应用的虚拟目录映射和主机搭建
首先来了解一下web的虚拟目录映射和主机搭建的知识 第一:web的虚拟目录映射 首先我们要知道什么叫做web的虚拟目录映射,这个很好理解的,就是将我们本地硬盘上的web应用映射出一个供外界用户访问的地 ...
- 如何启用Oracle EBS Form监控
前言: 有时候,因某些需要,必须知道Oracle的Form被使用的情况,以方面我们做出决策: 例如,如果某个Form被使用的次数非常多,那么,这个Form的相关SQL代码就应该优先处理,以减少服务器负 ...
- Linux的启动流程 (二)
引:本文以RedHat9.0和i386平台为例,剖析了从用户打开电源直到屏幕出现命令行提示符的整个Linux启动过程.并且介绍了启动中涉及到的各种文件.阅读Linux源代码,无疑是深入学习Linux的 ...
- Linux Debugging(三): C++函数调用的参数传递方法总结(通过gdb+反汇编)
上一篇文章<Linux Debugging:使用反汇编理解C++程序函数调用栈>没想到能得到那么多人的喜爱,因为那篇文章是以32位的C++普通函数(非类成员函数)为例子写的,因此只是一个特 ...
- 扩展GDAL,支持CNSDTF格式(一)
扩展GDAL,支持CNSDTF格式(一) 一. 简介 本文主要根据<中华人民共和国国家标准GB/T17798-2007--地理空间数据交换格式(Geospatialdata tra ...
- android:background="@color/white" [create file color.xml at res/values/]
<resources><color name="white">#FFFFFF</color><!--白色 --><col ...
- rhel6.4 安装 mysql-5.6
rhel6.4 安装 mysql-5.6 下载(临时地址, 如不可用,请到oracle官网下载) 采用rpm安装. mysql服务端要安装: ftp://pepstack.com/pub/rpm/My ...
- linux 下停止java jar包 shell
linux 下停止java jar包 shell http://injavawetrust.iteye.com #!/bin/sh APP_HOME=/home/ap/injavawetrust/ba ...
- python import自己编写的模块:import json和simplejson
python import的模块都是库里面的,而自己的模块也可以添加 比如python的json处理,库里没有json文件,import json不行. 网上大部分人告诉你处理json用 dumps和 ...
- Mysql数据库安装和配置
http://blog.csdn.net/pipisorry/article/details/46773507 Mysql数据库安装和配置.mysql语法.特殊符号及正则表达式的使用.MySQL备份与 ...