「IM系列」WebSocket教程:跨语言 WebSocketd 让实时通信更简单!

WebSocketd 是WebSocket的守护进程(命令行工具),负责处理WebSocket连接,并启动服务器应用程序来处理WebSockets,在应用程序和Web浏览器之间传递消息,无需任意依赖包且进程独立。WebSocketd是一款非常特别的WebSocket服务器,它的最大特点是后台脚本不限语言,其标准输入stdin就是WebSocket的输入,标准输出stdout就是WebSocket的输出。

安装

代码语言:javascript
复制
// 下载
wget https://github.com/joewalnes/websocketd/releases/download/v0.4.1/websocketd-0.4.1-linux_amd64.zip

// 解压
unzip websocketd-v0.4.1-linux_amd64.zip

解压后生成这个文件:websocketd

输入help查看看是否配置合适,如下所示:

代码语言:javascript
复制
./websocketd -version
websocketd 0.4.1 (go1.15.7 linux-amd64)

简单示例

shell脚本

计数器 counter.sh

代码语言:javascript
复制
#!/bin/bash
for ((COUNT = 1; COUNT <= 10; COUNT++)); do
echo $COUNT
sleep 1
done

启动websocketd

代码语言:javascript
复制
chmod 777 counter.sh
/var/www/websocketd/websocketd --port=8888 /var/www/websocketd/counter.sh

上面的命令会启动一个 WebSocket 服务器,端口是8888。每当客户端连接这个服务器,就会执行counter.sh脚本,并将它的输出推送给客户端。

预览

控制台

代码语言:javascript
复制
var ws = new WebSocket('ws://127.0.0.1/');
ws.onopen = function() {
console.log('CONNECT');
};
ws.onclose = function() {
console.log('DISCONNECT');
ws.close();
};
ws.onmessage = function(event) {
console.log('MESSAGE: ' + event.data);
};

HTML文件

代码语言:javascript
复制
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>开源技术小栈</title>
</head>
<body>
<h2>websocketd 客户端测试</h2>
<pre id="message" style="font-size: 24px;"></pre>
<script>
function log(msg) {
document.getElementById('message').textContent += msg + '\n';
}

var ws = new WebSocket(&#39;ws://127.0.0.1:8888/&#39;);
ws.onopen = function() {
    console.log(&#39;CONNECT&#39;);
};
ws.onclose = function() {
    console.log(&#39;DISCONNECT&#39;);
    ws.close();
};
ws.onmessage = function(event) {
    console.log(&#39;MESSAGE: &#39; + event.data);
    log(&#39;websocketd服务端响应:&#39;+event.data);
};

</script>
</body>
</html>

服务端打印日志

代码语言:javascript
复制
/var/www/websocketd # /var/www/websocketd/websocketd --port=8888 /var/www/websocketd/counter.sh
Sun, 24 Dec 2023 10:54:15 +0800 | INFO | server | | Serving using application : /var/www/websocketd/counter.sh
Sun, 24 Dec 2023 10:54:15 +0800 | INFO | server | | Starting WebSocket server : ws://4bc07756b82c/
Sun, 24 Dec 2023 10:54:32 +0800 | ACCESS | session | url:'http://127.0.0.1/' id:'1703386472745570850' remote:'172.18.0.1' command:'/var/www/websocketd/counter.sh' origin:'file:' | CONNECT
Sun, 24 Dec 2023 10:54:42 +0800 | ACCESS | session | url:'http://127.0.0.1/' id:'1703386472745570850' remote:'172.18.0.1' command:'/var/www/websocketd/counter.sh' origin:'file:' pid:'316' | DISCONNECT

实时监控内存信息

shell脚本

系统内存脚本 system_info.sh

代码语言:javascript
复制
#!/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin

SHELL_DIR="/var/www/websocketd"
SHELL_NAME="system_info"
SHELL_TIME=$(date '+%Y-%m-%d')
SHELL_LOG="{SHELL_DIR}/{SHELL_NAME}-${SHELL_TIME}.log"

REDIS_MEMORY_KEYS_NAME="REDIS_MEMORY_INFO:001"
REDIS_DISH_KEYS_NAME="REDIS_DISH_INFO:001"

while(true)
do
FIND_DATA=$(cat /proc/meminfo | grep "MemFree:" | awk '{print $2}')
echo "[SHELL_TIME]: FIND_DATA = FIND_DATA INSERT_RES = {INSERT_RES} CUT_LIST_LEN = {CUT_LIST_LEN}" >> $SHELL_LOG
echo '{"data":'"${FIND_DATA}"',"errcode":0,"errmsg":0}'
sleep 2
done

启动websocketd

代码语言:javascript
复制
chmod 777 counter.sh
/var/www/websocketd/websocketd --port=8888 /var/www/websocketd/counter.sh

HTML页面

代码语言:javascript
复制
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>开源技术小栈</title>
</head>
<body>
<h2>websocketd 客户端测试</h2>
<pre id="message" style="font-size: 24px;"></pre>
<script>
function log(msg) {
document.getElementById('message').textContent += msg + '\n';
}

var ws = new WebSocket(&#39;ws://127.0.0.1:8888/&#39;);
ws.onopen = function() {
    console.log(&#39;CONNECT&#39;);
};
ws.onclose = function() {
    console.log(&#39;DISCONNECT&#39;);
    ws.close();
};
ws.onmessage = function(event) {
    console.log(&#39;MESSAGE: &#39; + event.data);
    log(&#39;websocketd服务端响应:&#39;+event.data);
};

</script>
</body>
</html>

运行效果

参数配置

--staticdir=

--staticdir= 允许websocketd作为静态文件提供counter.html

count.sh 文件

代码语言:javascript
复制
#!/bin/bash
for COUNT in $(seq 1 10); do
echo $COUNT
sleep 1
done

count.html 文件

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
<title>websocketd count example</title>
<style>
#count {
font: bold 150px arial;
margin: auto;
padding: 10px;
text-align: center;
}
</style>
</head>
<body>

&lt;div id=&#34;count&#34;&gt;&lt;/div&gt;

&lt;script&gt;
  var ws = new WebSocket(&#39;ws://127.0.0.1:8888/&#39;);
  ws.onopen = function() {
    document.body.style.backgroundColor = &#39;#cfc&#39;;
  };
  ws.onclose = function() {
    document.body.style.backgroundColor = null;
  };
  ws.onmessage = function(event) {
    document.getElementById(&#39;count&#39;).textContent = event.data;
  };
&lt;/script&gt;

</body>
</html>

运行websocketd。注意参数--staticdir=. ./count.sh

代码语言:javascript
复制
/var/www/websocketd # /var/www/websocketd/websocketd --port=8888 --staticdir=. ./count.sh

Sun, 24 Dec 2023 11:29:57 +0800 | INFO | server | | Serving using application : ./count.sh
Sun, 24 Dec 2023 11:29:57 +0800 | INFO | server | | Serving static content from : .
Sun, 24 Dec 2023 11:29:57 +0800 | INFO | server | | Starting WebSocket server : ws://4bc07756b82c/
Sun, 24 Dec 2023 11:29:57 +0800 | INFO | server | | Serving CGI or static files : http://4bc07756b82c:8888/
Sun, 24 Dec 2023 11:30:01 +0800 | ACCESS | http | url:'http://127.0.0.1/count.html' | STATIC
Sun, 24 Dec 2023 11:30:01 +0800 | ACCESS | session | url:'http://127.0.0.1/' id:'1703388601564733656' remote:'172.18.0.1' command:'./count.sh' origin:'http://127.0.0.1' | CONNECT
Sun, 24 Dec 2023 11:30:11 +0800 | ACCESS | session | url:'http://127.0.0.1/' id:'1703388601564733656' remote:'172.18.0.1' command:'./count.sh' origin:'http://127.0.0.1' pid:'3571' | DISCONNECT

访问地址:http://127.0.0.1/count.html

开发者模式

为了帮助开发、调试和测试,websocketd包括一个开发人员控制台,使您可以轻松地与WebSocket端点进行交互,而无需编写JavaScript。要启用控制台,请在websocketd命令行选项中添加 --devconsole

运行websocketd

代码语言:javascript
复制
/var/www/websocketd/websocketd --port=8888 --dir=/var/www/websocketd --devconsole

浏览器访问:http://127.0.0.1/counter.sh

其他

守护进程运行

代码语言:javascript
复制
nohup /var/www/websocketd/websocketd --port=8888 /var/www/websocketd/system_info.sh  >/dev/null  2>&1 &

证书加载

代码语言:javascript
复制
sudo websocketd
--port=8888
--ssl
--sslcert="/etc/letsencrypt/live/www.tinywan.com/fullchain.pem"
--sslkey="/etc/letsencrypt/live/www.tinywan.com//privkey.pem"
/var/www/websocketd/system.sh

Nginx代理配置

代码语言:javascript
复制
server {
listen 443 ssl http2;
server_name wallet.tinywan.com;

ssl_certificate /etc/letsencrypt/wallet.tinywan.com/full_chain.pem;
ssl_certificate_key /etc/letsencrypt/wallet.tinywan.com/private.key;

location /wssd
{
    proxy_pass http://127.0.0.1:8888;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection &#34;Upgrade&#34;;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_read_timeout 600;
}

}

连接方式

代码语言:javascript
复制
var ws = new WebSocket('wss://wallet.tinywan.com/wssd');