例如有这样一个需求:

在终端上进行ping操作,现在想把这个这个操作放到web页面上进行,并且实现实时输出的效果。

来分析下具体实现过程

第一步,传统的http请求实现这个有点不太友好,因为这里边是一个请求,请求中间隔输出结果。  可以使用长轮询,这个以后再研究。

这种情况用websocket比较好。

然后再来解决几个疑惑,

怎么去写服务端的websocket?

方法: 这个选择比较多,python的很多框架里边都带有websocket模块,例如gevent-websocket,dwebsocket,flask_sockets

但是使用api却有不同,其实这些都是对socket进行来新的封装,所以这里用最原始的socket进行编程。

怎么发送websocket请求?

方法:发送websocket请求这个方法也比较多,有专门的第三方模块,例如websocket_client,jquery。这次是打算在web页面上显示,所以用jquery自带的api来请求服务端。

WebSocket 和 Socket 的区别,websocket 能连 socket 吗?

方法:就像Java和JavaScript,并没有什么太大的关系,但又不能说完全没关系。可以这么说,socket并不是一个协议,而是抽象出来的一层,应用于应用层和传输控制层之间的一组接口,socket是传输控制层协议,websocket是应用层协议。 jquery自带的api能有直接请求socket。

下边就直接上代码了

服务端:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import base64
import hashlib def get_headers(data):
"""
将请求头格式化成字典
:param data:
:return:
"""
header_dict = {}
data = str(data, encoding='utf-8') header, body = data.split('\r\n\r\n', 1)
header_list = header.split('\r\n')
for i in range(0, len(header_list)):
if i == 0:
if len(header_list[i].split(' ')) == 3:
header_dict['method'], header_dict['url'], header_dict['protocol'] = header_list[i].split(' ')
else:
k, v = header_list[i].split(':', 1)
header_dict[k] = v.strip()
return header_dict def send_msg(conn, msg_bytes):
"""
WebSocket服务端向客户端发送消息
:param conn: 客户端连接到服务器端的socket对象,即: conn,address = socket.accept()
:param msg_bytes: 向客户端发送的字节
:return:
"""
import struct token = b"\x81"
length = len(msg_bytes)
if length < 126:
token += struct.pack("B", length)
elif length <= 0xFFFF:
token += struct.pack("!BH", 126, length)
else:
token += struct.pack("!BQ", 127, length) msg = token + msg_bytes
conn.send(msg)
return True def run():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', 8003))
sock.listen(5) conn, address = sock.accept()
print(address)
data = conn.recv(1024)
print(data)
headers = get_headers(data)
response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \
"Upgrade:websocket\r\n" \
"Connection:Upgrade\r\n" \
"Sec-WebSocket-Accept:%s\r\n" \
"WebSocket-Location:ws://%s%s\r\n\r\n" value = headers['Sec-WebSocket-Key'] + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest())
response_str = response_tpl % (ac.decode('utf-8'), headers['Host'], headers['url'])
conn.send(bytes(response_str, encoding='utf-8')) while True:
try:
info = conn.recv(8096)
except Exception as e:
info = None
if not info:
break
payload_len = info[1] & 127
if payload_len == 126:
extend_payload_len = info[2:4]
mask = info[4:8]
decoded = info[8:]
elif payload_len == 127:
extend_payload_len = info[2:10]
mask = info[10:14]
decoded = info[14:]
else:
extend_payload_len = None
mask = info[2:6]
decoded = info[6:] bytes_list = bytearray()
for i in range(len(decoded)):
chunk = decoded[i] ^ mask[i % 4]
bytes_list.append(chunk)
body = str(bytes_list, encoding='utf-8') import subprocess
p = subprocess.Popen('ping -c5 www.baidu.com', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
lines = []
for line in iter(p.stdout.readline, b''):
line = line.rstrip().decode('utf8')
send_msg(conn, line.encode('utf-8')) sock.close() if __name__ == '__main__':
run()

客户端:

<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<script src="jquery-2.1.4.min.js"></script>
<script type="text/javascript">
$(function () {
var socket = new WebSocket("ws://127.0.0.1:8003");
$('#backup_all').click(function () {
console.log(window.location.host)
console.log(socket);
// socket.onopen = function () {
// console.log('WebSocket open');//成功连接上Websocket
// socket.send('ls');//发送数据到服务端
// };
socket.send('ls');
console.log('WebSocket open');//成功连接上Websocket socket.onmessage = function (e) {
console.log('message: ' + e.data);//打印服务端返回的数据
//$('#messagecontainer').prepend('<p><pre>' + e.data + '</pre></p>');
//$('#messagecontainer').prepend('<hr />');
$('#messagecontainer').append(e.data+'<br/>'); };
});
});
</script>
</head>
<body> <button style="margin: 20px;height: 40px;background-color: #00ff00;" type="button" id="backup_all" value="backup_all">
执行Shell脚本
</button>
<h3 style="margin: 20px;">脚本执行结果:</h3>
<div id="messagecontainer" style="margin: 20px;">
</div>
<hr/>
</body>
</html>

结果:

https://www.cnblogs.com/ssyfj/p/9245150.html

https://yq.aliyun.com/articles/656918

https://www.cnblogs.com/mengqingjian/p/8530994.html

最新文章

  1. ES6之let命令详解
  2. [家里蹲大学数学杂志]第033期稳态可压Navier-Stokes方程弱解的存在性
  3. [原创]Net实现Excel导入导出到数据库(附源码)
  4. export和import实现模块化
  5. iOS动画案例(1)
  6. js 原型,原型链,原型链继承浅析
  7. input file 重复上传同一张图片失效的解决办法
  8. ogg同步DDL时,源和目标端表空间名称不同的解决思路
  9. 浅谈如何使用Netty开发高性能的RPC服务器
  10. Yii2 nginx配置伪静态
  11. 能用padding,margin解决的不要使用伪元素,能用背景解决的也不要用伪元素
  12. eclipse代码提示javadoc背景为黑色框的解决办法
  13. [C#]使用Join与GroupJoin将两个集合进行关联与分组
  14. 使用Fakes的Stub和Shim对ASP.NET MVC4进行单元测试
  15. Spark程序本地运行
  16. 支持5G-WiFi的安卓设备搜索不到5G信号解决方法
  17. Android vcard使用示例,生成vcf文件
  18. Hive Tuning(一) 连接策略
  19. PTA | Maximum Subsequence Sum
  20. Maxscript-获取选中文件

热门文章

  1. Spring AOP编程经验总结
  2. CSS过渡效果transition和动画
  3. perl自定义简易的面向对象的栈与队列类
  4. 二零一八阿里p7笔试116题
  5. 第五章、drf-JWT认证
  6. 分布式爬虫-bilibili评论
  7. Windows工作原理
  8. 2018/7/31-zznuoj-问题 A: A + B 普拉斯【二维字符串+暴力模拟+考虑瑕疵的题意-0的特例】
  9. Seafile和Nextcloud相比较哪个好用
  10. python utf8