websocket+golang聊天室
原文地址:
http://www.niu12.com/article/3
websocket+golang聊天室 main.go和index.html放在同一目录下 main.go package main import (
"encoding/json"
"fmt"
"golang.org/x/net/websocket"
"net/http"
"time"
) type Message struct {
Username string
Message string
} type User struct {
Username string
} type Datas struct {
Messages []Message
Users []User
} // 全局信息
var datas Datas
var users map[*websocket.Conn]string func main() {
fmt.Println("启动时间: ", time.Now()) // 初始化数据
datas = Datas{}
users = make(map[*websocket.Conn]string) // 渲染页面
http.HandleFunc("/", index) // 监听socket方法
http.Handle("/webSocket", websocket.Handler(webSocket)) // 监听8080端口
http.ListenAndServe(":8889", nil)
} func index(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "index.html")
} func webSocket(ws *websocket.Conn) {
var message Message
var data string
for {
// 接收数据
err := websocket.Message.Receive(ws, &data)
if err != nil {
// 移除出错的连接
delete(users, ws)
fmt.Println("连接异常")
break
}
// 解析信息
err = json.Unmarshal([]byte(data), &message)
if err != nil {
fmt.Println("解析数据异常")
} // 添加新用户到map中,已经存在的用户不必添加
if _, ok := users[ws]; !ok {
users[ws] = message.Username
// 添加用户到全局信息
datas.Users = append(datas.Users, User{Username:message.Username})
}
// 添加聊天记录到全局信息
datas.Messages = append(datas.Messages, message) // 通过webSocket将当前信息分发
for key := range users{
err := websocket.Message.Send(key, data)
if err != nil{
// 移除出错的连接
delete(users, key)
fmt.Println("发送出错: " + err.Error())
break
}
}
}
}
index.html <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
<title>H5聊天室</title>
<style type="text/css">
.talk_con {
width: 100%;
height: 100%;
border: 1px solid #666;
margin: 50px auto 0;
background: #f9f9f9;
} .talk_show {
width: 100%;
height: 420px;
border: 1px solid #666;
background: #fff;
margin: 10px auto 0;
overflow: auto;
} .talk_input {
width: 100%;
} .talk_word {
width: 90%;
height: 26px;
float: left;
text-indent: 10px;
margin: 2% 5%;
} .talk_sub {
width: 100%;
height: 30px;
float: left;
} .atalk {
margin: 10px;
} .atalk span {
display: inline-block;
background: #0181cc;
border-radius: 10px;
color: #fff;
padding: 5px 10px;
} .btalk {
margin: 10px;
text-align: right;
} .btalk span {
display: inline-block;
background: #ef8201;
border-radius: 10px;
color: #fff;
padding: 5px 10px;
}
</style>
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
// 询问框获取用户昵称
let username = localStorage.getItem("username") ?
localStorage.getItem("username") : disp_prompt();
let words = $("#words");
let talkWords = $("#talkwords");
let talkSubmit = $("#talksub");
// webSocket
let wsURL = "ws://chat.niu12.com/webSocket";
ws = new WebSocket(wsURL);
try {
// 监听连接服务器
ws.onopen = function () {
console.log("已连接服务器")
}; // 监听关闭服务器
ws.onclose = function () {
if (ws) {
ws.close();
ws = null
}
console.log("关闭服务器连接")
}; // 监听信息
ws.onmessage = function (result) {
let data = JSON.parse(result.data);
let className = "atalk";
let user = data.username
// 如果是本人,放在右边 不是本人 放在左边
if (data.username === username){
className = "btalk";
user = "";
}
str = words.html() +
'<div class=" + className + ">'+user+'<span>'
+ data.message + '</span></div>';
words.html(str);
var scrollHeight = words.prop("scrollHeight");
words.scrollTop(scrollHeight);
}; // 监听错误
ws.onerror = function () {
if (ws) {
ws.close();
ws = null;
}
console.log("服务器连接失败")
}
} catch (e) {
console.log(e.message)
} document.onkeydown = function (event) {
let e = event || window.event;
if (e && e.keyCode === 13) { //回车键的键值为13
talkSubmit.click()
}
}; talkSubmit.click(function () {
// 获取输入框内容
let content = talkWords.val();
if (content === "") {
// 消息为空时弹窗
alert("消息不能为空");
return;
} // 发送数据
if (ws == null){
alert("连接服务器失败,请刷新页面");
window.location.reload();
return
}
let request = {"username":username, "message":content};
ws.send(JSON.stringify(request));
// 清空输入框
talkWords.val("")
})
}); function disp_prompt() {
let username = prompt("请输入昵称");
if (username == null || username === "") {
disp_prompt()
}else {
localStorage.setItem("username", username);
return username;
}
}
</script>
</head>
<body>
<h1>简易聊天室</h1>
<div class="talk_con">
<div class="talk_show" id="words"> </div>
<div class="talk_input">
<input type="text" class="talk_word" id="talkwords" placeholder="输入聊天内容">
<input type="button" value="发送" class="talk_sub" id="talksub">
</div>
</div>
</body>
</html>
websocket+golang聊天室的更多相关文章
- 基于WebSocket实现聊天室(Node)
基于WebSocket实现聊天室(Node) WebSocket是基于TCP的长连接通信协议,服务端可以主动向前端传递数据,相比比AJAX轮询服务器,WebSocket采用监听的方式,减轻了服务器压力 ...
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
- WebSocket 网页聊天室
先给大家开一个原始的websocket的连接使用范例 <?php /* * recv是从套接口接收数据,也就是拿过来,但是不知道是什么 * read是读取拿过来的数据,就是要知道recv过来的是 ...
- 关于websocket制作聊天室的的一些总结
websocket的总结 在一个聊天室系统中,常常使用websocket作为通信的主要方式.参考地址:https://www.jianshu.com/p/00e... 关于自己的看法:websocke ...
- python tornado websocket 多聊天室(返回消息给部分连接者)
python tornado 构建多个聊天室, 多个聊天室之间相互独立, 实现服务器端将消息返回给相应的部分客户端! chatHome.py // 服务器端, 渲染主页 --> 聊天室建立web ...
- nodejs+websocket制作聊天室视频教程
本套教程主要讲解了node平台的安装,node初级知识.node 服务器端程序响应http请求,通过npm安装第三方包,websocket即时通讯.聊天页面界面制作.拖动原理.拖动效果.遮罩效果.定位 ...
- 基于nodejs+webSocket的聊天室(实现:加入聊天室、退出聊天室、在线人数、在线列表、发送信息、接收信息)
1 安装 socket.io模块 npm install "socket.io": "latest" 2 app.js相关 ws = require('soc ...
- 第一节:.Net版基于WebSocket的聊天室样例
一. 说在前面的话 该篇文章为实时通讯系列的第一节,基于WebSocket编写了一个简易版聊天样例,主要作用是为引出后面SignalR系列的用法及其强大方便之处,通过这个样例与后续的SignalR对比 ...
- 基于webSocket的聊天室
前言 不知大家在平时的需求中有没有遇到需要实时处理信息的情况,如站内信,订阅,聊天之类的.在这之前我们通常想到的方法一般都是采用轮训的方式每隔一定的时间向服务器发送请求从而获得最新的数据,但这样会浪费 ...
随机推荐
- 修改mysql权限
关于mysql的用户管理,笔记 1.创建新用户 通过root用户登录之后创建 >> grant all privileges on *.* to testuser@localhost id ...
- 用JavaScript校验日期的合法性
校验表单时可能会遇到校验日期是否正确.可以利用JS的内置对象Date帮助我们完成日期校验. 思路是首先用被校验日期(假设为A,可能为字符串或数字)创建一个Date对象(假设为B). 然后判断A和B的年 ...
- HDU-1934
Car Plates Competition Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- 不断学习UI框架的写法
在web开发的过程中,我们会需要用到很多大大小小的插件,比如文本框,下拉树,下拉框等等各种各样的都需要.或许在开发的网页中会用到同一种插件来满足各种各样复杂的业务逻辑,比如简单的一个下拉树,有的地方需 ...
- Oracle 数据库分页查询的三种方法
一.Oracle 数据库分页查询的三种方法 1.简介 不能对 rownum 使用 >(大于或等于 1 的数值).>=(大于 1 的数值).=(不等于 1 的数值),否则无结果.所以直接用 ...
- Sonar常见的审查结果
格式:问题名字+问题出现的次数 Resources should be closed2 资源未关闭,打开发现有两处用到的IO流没有关闭 Conditions should not unconditio ...
- 图片乱码问题 解决方法 php
两个开发者都是下载同一个项目的git代码,但到本地环境,一个可以正常显示图片验证码,一个不行,找个半天开始以为环境问题 找了半天 不是 很多没说到重点 其实不只是当前文件格式问题 也要考虑其他调用文件 ...
- 2018CCPC 中国大学生程序设计竞赛 网络赛
链接 1.括号序列贪心/CF&51nod原题 [分析]: 贪心,每次到i的时候,假如你要在i里面要卖掉股票,获益是a[i], 肯定要在前面要么:1)把已经卖了的变成不买不卖,需要-a[j], ...
- js中复制方法总结
js中有深拷贝和浅拷贝两种复制形式,下面总结一下常用方法,方便平时工作复习使用 一.浅拷贝 1.json对象浅拷贝 var newObj = JSON.parse(JSON.stringify( so ...
- 一个菜鸟正在用SSH写一个论坛(1)
嗯..搞定了注册和登录,说明我的SSH整合已经没有问题了,那么我就继续折腾了. 我的目的是用SSH框架写一个论坛(当然是功能最简单的那种),搞定了整合之后我打算先做出一些基本的功能,于是我就先简单的设 ...