学生党福利使用websocket实现简单的聊天室

封面图片

前言

终于到了十一国庆,有时间更新一些东西了。
先从回忆开始。我是重邮的学生,记得上通信软件基础的时候,(@罗文丰)老师给我们留的作业是,写一个简单的聊天室。技术不限制。当时我想写一个web端聊天室。这条技术路线给我当时填了很多的麻烦。也就是说我要实现的是,web端的即时通信。web端我们可以用的协议是http。http是一个无状态的协议,怎么完成即使通信呢?当时自己脑壳都想废了。答案无非两种。

  1. 使用轮询。就是使用ajax过一段时间查询一次。
  2. 或者长连接。就是我发一个请求了,等有消息了在回复,然后处理了再发长连接。

可是那时我骄傲的认为都不好。都垃圾!怎么这就是现在业内的主流方案。不优雅!老子弄个更加牛逼的。结果搞出来了一个更加垃圾的。ajax+xml的方法。功能都没有实现是请求的时候获取更新的。(我当时固执的认为,网络效率要高,现在想想一个课程设计高个锤子!)
所以,我为学生党的你奉献出这个富有创造力的解决方案。

技术方案

websocket协议API传送门 + js
后端服务提供 websocketd 传送门
前端服务提供 http-server 传送门

注意 如果你以为这篇文章是给伸手党准备的,你就错了。你要在电脑上运行起这段代码。你至少要你学会一下这些技能。
git 安装运行linux虚拟机(windows用户) JavaScript只是了解dom 简单的计算机网络知识 翻墙技术(非必须)简单的shell脚本知识 但是不要紧张我保证这些知识花一周就可以掌握。而且遇到了困难了还可以问学长。欢迎评论和邮箱:)

原理

先简单的说一下这个websocket的协议(这个阮一峰的教程说的很好可以先传送一下看一下传送门)。他保证了一个到web的有状态连接。保证两边都是可以发送消息。这个对web开发即时场景来说简直太好了。
所以原来很简单。就是每个页面连接到一个ws(websocket)服务。然后把数据存到一个文件中,在读取这个文件中的信息返回给每个连接的用户。这里使用websocketd(注意多了一个d,这是一个提供websocket服务的服务器)。它很强大,它不分语言,只有在命令行里打包可以运行的命令他都可以进行提供服务。你甚至可以用c++写一个游戏服务器,给前端提供服务。如果各位感兴趣我可以在日后为大家完成demo。
所以,你可以看到这个原理是如此的简单,这都得益于优雅的websocket协议,富有创造力的websocketd服务器。

代码

客户端

代码很少。只有两个一个页面,和一个服务器脚本。这个没什么好说的,直接看代码吧;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<CTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>简单的聊天室</title>
</head>
<body>
<div id="content" >
<span>等待输出在开始通信</span>
<br>
</div>
<input type="text" id="input" />
<button type="submit" id="submit">发送</button>
<script>
//注意这里的地址 需要你进行修改!
var ws= new WebSocket('ws://zhouzihaodeMacBook-Pro.local:8080/');
var btn = document.getElementById("submit");
var text = document.getElementById("input");
var content = document.getElementById("content");
ws.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
content.innerHTML += event.data+"<br>";
});
ws.onclose = function(event){
console.log('closed');
}
//给按钮添加监听事件然后发送消息
btn.onclick = function(){
//如果内容为空就不发送出来
if(text.value == ''){
//donothing
}else{
ws.send(text.value);
//吧刚刚发的消息 回显出来
console.log('send'+text.value);
text.value = '';
}
}
</script>
</body>
</html>

服务端

然后是服务端的脚本。捂脸。这个都是我照着官方的demo抄的改的。看一下吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
# 代码源自websocketd官方项目的demo我做了一些小的修改!每次发消息的时候也会显示回来~
# 注意这是不需要的!我为了方便在这么做的。但是这加大了网络的io。正常做法是用js直接现在在页面里。
# 这段代码只能跑在 可以使用这些命令的机器上 的服务器上。如果你使用的是windows请检查这个文件是否可以使用。
# 或者我将在别的时间内。补充windows可用的版本
echo "Please enter your name:"; read USER
echo "[$(date)] ${USER} joined the chat" >> chat.log
echo "[$(date)] Welcome to the chat ${USER}!"
# 注意这里 这里如果没有生效要改成自己的地址
MYDIR=`pwd -L`
tail -n 0 -f "${MYDIR}/chat.log" &
while read MSG; do echo "[$(date)] ${USER}> ${MSG}" >> chat.log; done

最后是我的git代码传送门

结果

首先启动文件夹下的chat为websocket服务。
websocket --port=8080 $project-dir$/chat
这里的project_dir是项目文件夹的绝对路径。
然后在把index.html发布成web就可以了。
http-server
之后按照提示访问就好。为了看效果要开两个tab来看。
结果

我将一直迷惑和无知,我是黄油香蕉君,再见。

给作者买杯咖啡吧。喵~