原文地址:

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聊天室的更多相关文章

  1. 基于WebSocket实现聊天室(Node)

    基于WebSocket实现聊天室(Node) WebSocket是基于TCP的长连接通信协议,服务端可以主动向前端传递数据,相比比AJAX轮询服务器,WebSocket采用监听的方式,减轻了服务器压力 ...

  2. Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G

    code&monkey   Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...

  3. WebSocket 网页聊天室

    先给大家开一个原始的websocket的连接使用范例 <?php /* * recv是从套接口接收数据,也就是拿过来,但是不知道是什么 * read是读取拿过来的数据,就是要知道recv过来的是 ...

  4. 关于websocket制作聊天室的的一些总结

    websocket的总结 在一个聊天室系统中,常常使用websocket作为通信的主要方式.参考地址:https://www.jianshu.com/p/00e... 关于自己的看法:websocke ...

  5. python tornado websocket 多聊天室(返回消息给部分连接者)

    python tornado 构建多个聊天室, 多个聊天室之间相互独立, 实现服务器端将消息返回给相应的部分客户端! chatHome.py // 服务器端, 渲染主页 --> 聊天室建立web ...

  6. nodejs+websocket制作聊天室视频教程

    本套教程主要讲解了node平台的安装,node初级知识.node 服务器端程序响应http请求,通过npm安装第三方包,websocket即时通讯.聊天页面界面制作.拖动原理.拖动效果.遮罩效果.定位 ...

  7. 基于nodejs+webSocket的聊天室(实现:加入聊天室、退出聊天室、在线人数、在线列表、发送信息、接收信息)

    1  安装 socket.io模块 npm install "socket.io": "latest" 2 app.js相关 ws = require('soc ...

  8. 第一节:.Net版基于WebSocket的聊天室样例

    一. 说在前面的话 该篇文章为实时通讯系列的第一节,基于WebSocket编写了一个简易版聊天样例,主要作用是为引出后面SignalR系列的用法及其强大方便之处,通过这个样例与后续的SignalR对比 ...

  9. 基于webSocket的聊天室

    前言 不知大家在平时的需求中有没有遇到需要实时处理信息的情况,如站内信,订阅,聊天之类的.在这之前我们通常想到的方法一般都是采用轮训的方式每隔一定的时间向服务器发送请求从而获得最新的数据,但这样会浪费 ...

随机推荐

  1. debian 7 安装 rz sz lrzsz

    https://blog.csdn.net/hchaoyangming/article/details/51582749

  2. 【JBPM4】任务节点-任务分配assignment-Handler

    JPDL <?xml version="1.0" encoding="UTF-8"?> <process key="task&quo ...

  3. hdu5756

    http://www.cnblogs.com/duoxiao/p/5777644.html 官方题解在这里 其实这道题不难,当初训练的时候不会做说明自己太弱 lazy标记不pushdown就是用laz ...

  4. electron-builder中NSIS相关配置

    electron-builder中NSIS相关配置 相比较于electron-packager打包,使用electron-builder打包使得包体积更小.在electron-builder中,对于N ...

  5. Qt发布可能遇到的问题

    1.首先要搞清楚动态链接库还是静态链接 本文只涉及动态链接库,就是编译出来的exe文件加上Qt 的必要dll文件. 一般跟别人一样的操作,直接双击 XX.exe,提示缺少什么dll,就去Qt的安装目录 ...

  6. nginx应用场景,特性,目录结构,常用模块,内置变量,URL和URI,http状态码,配置文件详解

    1.nginx介绍 1丶俄罗斯人开发的,开源www服务软件 2丶软件一共780K 3丶nginx本身是一款静态(html,js,css,jpg等)www软件 4丶静态小文件高并发,同时占用的资源很少, ...

  7. iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8001 -j DNAT --to-destination 172.17.0.5:8080 ! -i docker0: iptables: No chain/target/match by that name.

    在docker容器上部署项目后,启动docker容器,出现 iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dpor ...

  8. ExtJs之组件(window)

    Ext.create('Ext.window.Window',{    title:'',    width:400,    height:300,    constrain:true,//限制窗口不 ...

  9. 洛谷——P1529 回家 Bessie Come Home

    P1529 回家 Bessie Come Home 题目描述 现在是晚餐时间,而母牛们在外面分散的牧场中. 农民约翰按响了电铃,所以她们开始向谷仓走去. 你的工作是要指出哪只母牛会最先到达谷仓(在给出 ...

  10. 洛谷——P1292 倒酒

    P1292 倒酒 题目描述 Winy是一家酒吧的老板,他的酒吧提供两种体积的啤酒,a ml和b ml,分别使用容积为a ml和b ml的酒杯来装载. 酒吧的生意并不好.Winy发现酒鬼们都非常穷.有时 ...