2019年6月

与同学合租服使用的简单工具。

const start_comm = ['-jar','minecraft_server.jar'];
const ws = require('nodejs-websocket');
// exec(),spawn(),fork()
// 参考:https://www.cnblogs.com/chyingp/p/node-learning-guide-child_process.html
const mcprocess = require('child_process').spawn('java',start_comm);
var client = null;
var process = true;
function mcprocess_log(log){
        console.log(String(log));
        if(client){
                client.sendText(String(log));
        }
}
mcprocess.stdout.on('data',mcprocess_log); // 输出/错误事件绑定
mcprocess.stdout.on('data',mcprocess_log);
mcprocess.on('exit',(code) => process = false); // 子进程退出事件
var server = ws.createServer(function(conn){
        client = conn;
        conn.on('text',function(str){ // 消息事件
                console.log(str);
                if(process){
                        conn.sendText(str + '\n');
                        mcprocess.stdin.write(str + '\n');
                }else{
                        conn.sendText('服务器未开启\n');
                }
        });
        conn.on('close',function(code,reason){ // 断开事件
                console.log('客户端断开连接');
                client = null;
        });
}).listen(8080);
console.log('start...');

Html还是和上几篇文章一样:

<title>WebSockets Test</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
var ws = new WebSocket("ws://server_ip:8080/");
ws.onmessage = function(msg){
        $('.message').append("<p>" + msg.data + "</p>");
}
ws.onclose = function(){
        $('.message').append("<p>Connection closed</p>");
}
function sendmsg(){
        var msg = $("#msg").val();
        ws.send(msg);
}
</script>
<div class='message'></div>
<textarea id="msg"></textarea>
<button type="but" onclick="sendmsg()">Send</button>

实际上服务器上使用的是我写的另外一个Python版本的,与Nodejs不同的是我需要新建一个线程去关注服务器核心的输出,所以简单尝试了Nodejs。

71_0.png

据说是官方推荐的部署方式。通过Lighttpd的Fastcgi来部署。
适合部署些小应用。

1 安装环境

#安装Lighttpd
apt-get install lighttpd
#安装Webpy及其依赖
pip install web.py flup

2 配置Fastcgi

通过apt方式安装的,配置在/etc/lighttpd目录下

#lighttpd.conf
#添加模块
    "mod_rewrite"
    "mod_fastcgi"
#在static-file.exclude-extensions中添加
    ".py"
#在include_shell前添加配置
    fastcgi.server = ( ".py" =>
        (( "socket" => "/tmp/fastcgi.socket", #fastcgi名
            "bin-path" => "/var/www/html/index.py", #应用入口文件
            "max-procs" => 3, #子进程个数
            "bin-environment" => (
                "REAL_SCRIPT_NAME" => ""
            ),
            "check-local" => "disable"
        )))
#转发配置
    url.rewrite-once = (
        "^/favicon.ico$" => "/static/favicon.ico",
        "^/static/(.*)$" => "/static/$1",
        "^/(.*)$" => "/index.py/$1",
    )

3 重启&测试

重启:

service lighttpd restart

测试用例(index.py):

#coding=utf-8
import web
urls = (
    "/(.*)", "index",
)
app = web.application(urls, globals())
class index:
    def GET(self, name):
        web.header('Content-Type','text/html; charset=UTF-8')
        return "Hello " + name
if __name__ == "__main__":
    app.run()

现在可以访问不同的路径康康效果:

http://localhost/
http://localhost/test

这次使用Python来进行Websocket通信,使用Tornado自带的Websocket库,与游览器自带的api。

目录结构

.
├── static
│   └── index.html
└── websockettest.py

Python

#coding=utf-8
import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop

client_list = [] #连接用户列表

class WebSocketHandler(tornado.websocket.WebSocketHandler):
        def open(self): #连接进入
                #print(dir(self)) #康康对象有什么
                client_list.append(self)
                pass
        def on_message(self,message): #消息事件
                print(message)
                for client in client_list: #将消息发送到所有在线的连接
                        client.write_message(message)
        def on_close(self): #关闭事件
                client_list.remove(self)
                pass
        def check_origin(self,origin): #允许跨域访问
                print(origin)
                return True
class IndexPageHandler(tornado.web.RequestHandler):
        def get(self):
                self.render('index.html')

class Application(tornado.web.Application):
        def __init__(self):
                handlers = [(r'/',IndexPageHandler),(r'/websocket',WebSocketHandler)]
                settings = {'template_path':'static'} #设置模板文件目录
                tornado.web.Application.__init__(self,handlers,**settings)

if __name__ == '__main__':
        app = Application()
        tornado.httpserver.HTTPServer(app).listen(80)
        tornado.ioloop.IOLoop.instance().start()

Html & JavaSscript

<title>WebSockets Test</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
var ws = new WebSocket("ws://ip/websocket"); #你可以在本地保存网页测试(跨域请求)
//ws.onopen = function(){
//      ws.send('hello!');
//}
ws.onmessage = function(msg){
        $('.message').append("<p>" + msg.data + "</p>");
}
ws.onclose = function(){
        $('.message').append("<p>Connection closed</p>");
}
function sendmsg(){
        var msg = $("#msg").val();
        ws.send(msg);
}
</script>
<div class='message'></div>
<textarea id="msg"></textarea>
<button type="but" onclick="sendmsg()">Send</button>

其他

上次Nodejs的Express-ws网页测试不成功的原因是Socket.io的问题,Socket.io会向socket.io/?EIO=&transport=websocket请求连 接,只有服务端一起使用Socket.io才能正常连接,使用游览器自带访问正常连接(更新:之前不了解Socket.io的工作模式写的不对的话)。