python---websocket的使用
一:简介
推文:WebSocket 是什么原理?为什么可以实现持久连接?
推文:WebSocket:5分钟从入门到精通(很好)
WebSocket协议是基于TCP的一种新的协议。WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符。它实现了浏览器与服务器全双工(full-duplex)通信。其本质是保持TCP连接,在浏览器和服务端通过Socket进行通信。
二:对比:
Http:
socket实现,单工通道(浏览器只发起,服务端只做响应),短连接,请求响应
WebSocket:
socket实现,双工通道,请求响应,推送。socket创建连接,不断开
三:socket实现步骤
服务端:
. 服务端开启socket,监听IP和端口
. 允许连接
* . 服务端接收到特殊值【加密sha1,特殊值,migic string="258EAFA5-E914-47DA-95CA-C5AB0DC85B11"】
* . 加密后的值发送给客户端
客户端:
. 客户端发起连接请求(IP和端口)
* . 客户端生成一个xxx,【加密sha1,特殊值,migic string="258EAFA5-E914-47DA-95CA-C5AB0DC85B11"】,向服务端发送一段特殊值
* . 客户端接收到加密的值
注意:这个魔数是固定的 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
四:简单实现,实现连接
服务端:
# coding:utf8
# __author: Administrator
# date: //
# /usr/bin/env python
import socket,base64,hashlib def get_headers(data):
'''将请求头转换为字典'''
header_dict = {}
data = str(data,encoding="utf-8") header,body = data.split("\r\n\r\n",)
header_list = header.split("\r\n")
for i in range(,len(header_list)):
if i == :
if len(header_list[].split(" ")) == :
header_dict['method'],header_dict['url'],header_dict['protocol'] = header_list[].split(" ")
else:
k,v=header_list[i].split(":",)
header_dict[k]=v.strip()
return header_dict sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,)
sock.bind(("127.0.0.1",))
sock.listen() #等待用户连接
conn,addr = sock.accept()
print("conn from ",conn,addr)
#获取握手消息,magic string ,sha1加密
#发送给客户端
#握手消息
data = conn.recv()
headers = get_headers(data) # 对请求头中的sec-websocket-key进行加密
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" magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' value = headers['Sec-WebSocket-Key'] + magic_string
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'))
'''
b'
GET / HTTP/1.1\r\n
Host: 127.0.0.1:\r\n
Connection: Upgrade\r\n
Pragma: no-cache\r\n
Cache-Control: no-cache\r\n
Upgrade: websocket\r\n
Origin: http://localhost:63342\r\n
Sec-WebSocket-Version: \r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.8\r\n
Sec-WebSocket-Key: +uL/aiakjNABjEoMzAqm6Q==\r\n
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n'
'''
请求头
浏览器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> </body>
</html>
<script>
ws =new WebSocket("ws://127.0.0.1:8080");
ws.onopen = function (ev) { //若是连接成功,onopen函数会执行
console.log()
}
</script>
五:数据接收规则
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length | #Payload len(第二个字节的前七位,最大127)决定头部的长度
|I|S|S|S| () |A| () | (/) | #若是小于126:Extended payload length扩展头部长度为0字节,后面全部为主体数据
|N|V|V|V| |S| | (if payload len==/) | #若是等于126:Extended payload length扩展头部长度为2字节,后面全部为主体数据
| |||| |K| | | #若是等于127:Extended payload length扩展头部长度为8字节,后面全部为主体数据
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == | #注意:主体数据中的前四位为mask掩码,用于后面的消息的解码,解码方式为循环异或操作
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to | #数据过长,需要分部发送,这时需要FIN和opcode
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
The MASK bit simply tells whether the message is encoded. Messages from the client must be masked, so your server should expect this to be . (In fact, section 5.1 of the spec says that your server must disconnect from a client if that client sends an unmasked message.) When sending a frame back to the client, do not mask it and do not set the mask bit. We'll explain masking later. Note: You have to mask messages even when using a secure socket.RSV1-3 can be ignored, they are for extensions. The opcode field defines how to interpret the payload data: 0x0 for continuation, 0x1 for text (which is always encoded in UTF-), 0x2 for binary, and other so-called "control codes" that will be discussed later. In this version of WebSockets, 0x3 to 0x7 and 0xB to 0xF have no meaning. The FIN bit tells whether this is the last message in a series. If it's 0, then the server will keep listening for more parts of the message; otherwise, the server should consider the message delivered. More on this later. Decoding Payload Length To read the payload data, you must know when to stop reading. That's why the payload length is important to know. Unfortunately, this is somewhat complicated. To read it, follow these steps: Read bits - (inclusive) and interpret that as an unsigned integer. If it's 125 or less, then that's the length; you're done. If it's , go to step . If it's 127, go to step 3.
Read the next bits and interpret those as an unsigned integer. You're done.
Read the next bits and interpret those as an unsigned integer (The most significant bit MUST be ). You're done.
Reading and Unmasking the Data If the MASK bit was set (and it should be, for client-to-server messages), read the next octets ( bits); this is the masking key. Once the payload length and masking key is decoded, you can go ahead and read that number of bytes from the socket. Let's call the data ENCODED, and the key MASK. To get DECODED, loop through the octets (bytes a.k.a. characters for text data) of ENCODED and XOR the octet with the (i modulo 4)th octet of MASK. In pseudo-code (that happens to be valid JavaScript): var DECODED = "";
for (var i = ; i < ENCODED.length; i++) {
DECODED[i] = ENCODED[i] ^ MASK[i % ];
} Now you can figure out what DECODED means depending on your application.
数据帧格式:
FIN:1个比特。
如果是1,表示这是消息(message)的最后一个分片(fragment),如果是0,表示不是是消息(message)的最后一个分片(fragment)。
RSV1, RSV2, RSV3:各占1个比特。
一般情况下全为0。当客户端、服务端协商采用WebSocket扩展时,这三个标志位可以非0,且值的含义由扩展进行定义。如果出现非零的值,且并没有采用WebSocket扩展,连接出错。
Opcode: 4个比特。
操作代码,Opcode的值决定了应该如何解析后续的数据载荷(data payload)。如果操作代码是不认识的,那么接收端应该断开连接(fail the connection)。可选的操作代码如下: %x0:表示一个延续帧。当Opcode为0时,表示本次数据传输采用了数据分片,当前收到的数据帧为其中一个数据分片。
%x1:表示这是一个文本帧(frame)
%x2:表示这是一个二进制帧(frame)
%x3-:保留的操作代码,用于后续定义的非控制帧。
%x8:表示连接断开。
%x9:表示这是一个ping操作。
%xA:表示这是一个pong操作。
%xB-F:保留的操作代码,用于后续定义的控制帧。
Mask: 1个比特。
表示是否要对数据载荷进行掩码操作。从客户端向服务端发送数据时,需要对数据进行掩码操作;从服务端向客户端发送数据时,不需要对数据进行掩码操作。 如果服务端接收到的数据没有进行过掩码操作,服务端需要断开连接。 如果Mask是1,那么在Masking-key中会定义一个掩码键(masking key),并用这个掩码键来对数据载荷进行反掩码。所有客户端发送到服务端的数据帧,Mask都是1。 掩码的算法、用途在下一小节讲解。
Payload length:数据载荷的长度,单位是字节。为7位,或7+16位,或1+64位。
假设数Payload length === x,如果 x为0~:数据的长度为x字节。
x为126:后续2个字节代表一个16位的无符号整数,该无符号整数的值为数据的长度。
x为127:后续8个字节代表一个64位的无符号整数(最高位为0),该无符号整数的值为数据的长度。
此外,如果payload length占用了多个字节的话,payload length的二进制表达采用网络序(big endian,重要的位在前)。
Masking-key:0或4字节(32位)
所有从客户端传送到服务端的数据帧,数据载荷都进行了掩码操作,Mask为1,且携带了4字节的Masking-key。如果Mask为0,则没有Masking-key。 备注:载荷数据的长度,不包括mask key的长度。
Payload data:(x+y) 字节
载荷数据:包括了扩展数据、应用数据。其中,扩展数据x字节,应用数据y字节。 扩展数据:如果没有协商使用扩展的话,扩展数据数据为0字节。所有的扩展都必须声明扩展数据的长度,或者可以如何计算出扩展数据的长度。此外,扩展如何使用必须在握手阶段就协商好。如果扩展数据存在,那么载荷数据长度必须将扩展数据的长度包含在内。 应用数据:任意的应用数据,在扩展数据之后(如果存在扩展数据),占据了数据帧剩余的位置。载荷数据长度 减去 扩展数据长度,就得到应用数据的长度。
实现规则解码:
def get_data(info): #info是我们连接后,接受的数据
payload_len = info[] &
if payload_len == :
extend_payload_len = info[:]
mask = info[:]
decoded = info[:]
elif payload_len == :
extend_payload_len = info[:]
mask = info[:]
decoded = info[:]
else:
extend_payload_len = None
mask = info[:]
decoded = info[:] bytes_list = bytearray() #这里我们使用字节将数据全部收集,再去字符串编码,这样不会导致中文乱码
for i in range(len(decoded)):
chunk = decoded[i] ^ mask[i % ]
bytes_list.append(chunk)
body = str(bytes_list, encoding='utf-8')
return body
实现循环获取数据
import socket,base64,hashlib def get_headers(data):
'''将请求头转换为字典'''
header_dict = {}
data = str(data,encoding="utf-8") header,body = data.split("\r\n\r\n",)
header_list = header.split("\r\n")
for i in range(,len(header_list)):
if i == :
if len(header_list[].split(" ")) == :
header_dict['method'],header_dict['url'],header_dict['protocol'] = header_list[].split(" ")
else:
k,v=header_list[i].split(":",)
header_dict[k]=v.strip()
return header_dict def get_data(info):
payload_len = info[] &
if payload_len == :
extend_payload_len = info[:]
mask = info[:]
decoded = info[:]
elif payload_len == :
extend_payload_len = info[:]
mask = info[:]
decoded = info[:]
else:
extend_payload_len = None
mask = info[:]
decoded = info[:] bytes_list = bytearray() #这里我们使用字节将数据全部收集,再去字符串编码,这样不会导致中文乱码
for i in range(len(decoded)):
chunk = decoded[i] ^ mask[i % ] #解码方式
bytes_list.append(chunk)
body = str(bytes_list, encoding='utf-8')
return body sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,)
sock.bind(("127.0.0.1",))
sock.listen() #等待用户连接
conn,addr = sock.accept()
print("conn from ",conn,addr)
#获取握手消息,magic string ,sha1加密
#发送给客户端
#握手消息
data = conn.recv() headers = get_headers(data) # 对请求头中的sec-websocket-key进行加密
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" magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' value = headers['Sec-WebSocket-Key'] + magic_string
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:
data = conn.recv()
data = get_data(data)
print(data)
服务端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> </body>
</html>
<script>
ws =new WebSocket("ws://127.0.0.1:8080");
ws.onopen = function (ev) { //若是连接成功,onopen函数会执行
console.log();
ws.send("你好");
}
</script>
客户端代码

注意:使用控制台完成发送,而不是刷新页面,会报错,因为我们关闭了连接,试图将关闭信号字节编码出错。这里我们需要利用mask(第二字节中,1表示连接,0断开)
六:数据发送规则(需要发送二进制包struct模块)
def send_msg(conn, msg_bytes):
"""
WebSocket服务端向客户端发送消息
:param conn: 客户端连接到服务器端的socket对象,即: conn,address = socket.accept()
:param msg_bytes: 向客户端发送的字节
:return:
"""
import struct token = b"\x81" #接收的第一字节,一般都是x81不变
length = len(msg_bytes)
if length < :
token += struct.pack("B", length)
elif length <= 0xFFFF:
token += struct.pack("!BH", , length)
else:
token += struct.pack("!BQ", , length) msg = token + msg_bytes
conn.send(msg)
return True

实现发送数据
# coding:utf8
# __author: Administrator
# date: //
# /usr/bin/env python
import socket,base64,hashlib def get_headers(data):
'''将请求头转换为字典'''
header_dict = {}
data = str(data,encoding="utf-8") header,body = data.split("\r\n\r\n",)
header_list = header.split("\r\n")
for i in range(,len(header_list)):
if i == :
if len(header_list[].split(" ")) == :
header_dict['method'],header_dict['url'],header_dict['protocol'] = header_list[].split(" ")
else:
k,v=header_list[i].split(":",)
header_dict[k]=v.strip()
return header_dict def get_data(info):
payload_len = info[] &
if payload_len == :
extend_payload_len = info[:]
mask = info[:]
decoded = info[:]
elif payload_len == :
extend_payload_len = info[:]
mask = info[:]
decoded = info[:]
else:
extend_payload_len = None
mask = info[:]
decoded = info[:] bytes_list = bytearray() #这里我们使用字节将数据全部收集,再去字符串编码,这样不会导致中文乱码
for i in range(len(decoded)):
chunk = decoded[i] ^ mask[i % ] #解码方式
bytes_list.append(chunk)
body = str(bytes_list, encoding='utf-8')
return body def send_msg(conn, msg_bytes):
"""
WebSocket服务端向客户端发送消息
:param conn: 客户端连接到服务器端的socket对象,即: conn,address = socket.accept()
:param msg_bytes: 向客户端发送的字节
:return:
"""
import struct token = b"\x81" #接收的第一字节,一般都是x81不变
length = len(msg_bytes)
if length < :
token += struct.pack("B", length)
elif length <= 0xFFFF:
token += struct.pack("!BH", , length)
else:
token += struct.pack("!BQ", , length) msg = token + msg_bytes
conn.send(msg)
return True sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,)
sock.bind(("127.0.0.1",))
sock.listen() #等待用户连接
conn,addr = sock.accept()
#获取握手消息,magic string ,sha1加密
#发送给客户端
#握手消息
data = conn.recv() headers = get_headers(data) # 对请求头中的sec-websocket-key进行加密
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" magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' value = headers['Sec-WebSocket-Key'] + magic_string
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:
data = conn.recv()
data = get_data(data)
print(data)
send_msg(conn,bytes(data+"geah",encoding="utf-8"))
服务端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> </body>
</html>
<script>
ws =new WebSocket("ws://127.0.0.1:8080");
ws.onopen = function (ev) { //若是连接成功,onopen函数会执行
console.log();
ws.send("你好");
}
ws.onmessage = function (ev) {
console.log(ev);
}
</script>
前端onmessage 当数据接收会触发

七:tornado实现websocket聊天室
tornado服务端
import tornado.ioloop
import tornado.web
import tornado.websocket
import datetime class MainHandler(tornado.web.RequestHandler):
def get(self): self.render("s1.html") def post(self, *args, **kwargs):
pass users = set()
class ChatHandler(tornado.websocket.WebSocketHandler):
def open(self, *args, **kwargs):
'''客户端连接'''
print("connect....")
print(self.request)
users.add(self) def on_message(self, message):
'''有消息到达'''
now = datetime.datetime.now()
content = self.render_string("recv_msg.html",date=now.strftime("%Y-%m-%d %H:%M:%S"),msg=message)
for client in users:
if client == self:
continue
client.write_message(content) def on_close(self):
'''客户端主动关闭连接'''
users.remove(self) st ={
"template_path": "template",#模板路径配置
"static_path":'static',
} #路由映射 匹配执行,否则404
application = tornado.web.Application([
("/index",MainHandler),
("/wschat",ChatHandler),
],**st) if __name__=="__main__":
application.listen() #io多路复用
tornado.ioloop.IOLoop.instance().start()
前端模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/css/nifty.min.css" rel="stylesheet">
<link href="/static/css/demo/nifty-demo-icons.min.css" rel="stylesheet">
<link href="/static/css/demo/nifty-demo.min.css" rel="stylesheet">
<link href="/static/plugins/pace/pace.min.css" rel="stylesheet">
<script src="/static/js/jquery-2.2.4.min.js"></script>
<script src="/static/plugins/pace/pace.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<script src="/static/js/nifty.min.js"></script>
<script src="/static/js/demo/nifty-demo.min.js"></script>
<script src="/static/plugins/flot-charts/jquery.flot.min.js"></script>
<script src="/static/plugins/flot-charts/jquery.flot.resize.min.js"></script>
<script src="/static/plugins/gauge-js/gauge.min.js"></script>
<script src="/static/plugins/skycons/skycons.min.js"></script>
<script src="/static/plugins/easy-pie-chart/jquery.easypiechart.min.js"></script>
<script src="/static/js/demo/widgets.js"></script>
</head>
<body>
<div id="container" class="effect aside-bright mainnav-sm aside-right aside-in">
<div class="boxed">
<div id="content-container">
<div class="row">
<div class="col-md-8 col-lg-8 col-sm-8"> <!--Chat widget-->
<!--===================================================-->
<div class="panel" style="height: 640px">
<!--Heading-->
<div class="panel-heading">
<h3 class="panel-title">Chat</h3>
</div> <!--Widget body-->
<div style="height:510px;padding-top:0px;" class="widget-body">
<div class="nano">
<div class="nano-content pad-all">
<ul class="list-unstyled media-block"> </ul>
</div>
</div> <!--Widget footer-->
<div class="panel-footer" style="height: 90px;">
<div class="row">
<div class="col-xs-9">
<input type="text" placeholder="Enter your text" class="form-control chat-input">
</div>
<div class="col-xs-3">
<button class="btn btn-primary btn-block" onclick="sendMsg(this);" type="submit">Send</button>
</div>
</div>
</div>
</div>
</div>
<!--===================================================-->
<!--Chat widget--> </div>
<div class="col-md-4 col-lg-4 col-sm-4">
<aside id="aside-container">
<div id="aside">
<div class="nano has-scrollbar">
<div class="nano-content" tabindex="" style="right: -17px;"> <!--Nav tabs-->
<!--================================-->
<ul class="nav nav-tabs nav-justified">
<li class="active">
<a href="#demo-asd-tab-1" data-toggle="tab">
<i class="demo-pli-speech-bubble-7"></i>
</a>
</li>
</ul>
<!--================================-->
<!--End nav tabs--> <!-- Tabs Content -->
<!--================================-->
<div class="tab-content">
<div class="tab-pane fade in active" id="demo-asd-tab-1">
<p class="pad-hor text-semibold text-main">
<span class="pull-right badge badge-success"></span> Friends
</p> </div>
</div>
</div>
<div class="nano-pane" style="display: none;"><div class="nano-slider" style="height: 4059px; transform: translate(0px, 0px);"></div></div></div>
</div>
</aside>
</div>
</div>
</div>
</div>
</div>
</body>
</html> <script>
ws = new WebSocket("ws://127.0.0.1:8080/wschat"); function sendMsg(ths) {
var dt = new Date()
var now_time = dt.toLocaleString(); var msg = $(ths).parents(".row").find(".chat-input").val();
$(ths).parents(".row").find(".chat-input").empty();
var li = '<li class="mar-btm"><div class="media-right"><img src="" class="img-circle img-sm" alt="Profile Picture"></div>';
li += '<div class="media-body pad-hor speech-right"><div class="speech"><a href="#" class="media-heading">游客</a>';
li += '<p>'+msg+'</p>';
li += '<p class="speech-time">';
li += '<i class="demo-pli-clock icon-fw"></i>'+now_time;
li += '</p></div></div></li>';
$(ths).parents(".widget-body").find(".list-unstyled").append(li);
$(ths).parents(".panel-footer").find(".chat-input").val("");
ws.send(msg);
} ws.onmessage=function (ev) {
$(".list-unstyled").append(ev.data);
}
</script>
s1.html
消息插件
<li class="mar-btm">
<div class="media-left">
<img src="img/profile-photos/1.png" class="img-circle img-sm" alt="Profile Picture">
</div>
<div class="media-body pad-hor">
<div class="speech">
<a href="#" class="media-heading">游客</a>
<p>{{msg}}</p>
<p class="speech-time">
<i class="demo-pli-clock icon-fw"></i>{{date}}
</p>
</div>
</div>
</li>
recv_msg.html
实现效果
游客一:

游客二

python---websocket的使用的更多相关文章
- Python WebSocket长连接心跳与短连接
python websocket 安装 pip install websocket-client 先来看一下,长连接调用方式: ws = websocket.WebSocketApp("ws ...
- python websocket学习使用
前言 今天看了一些资料,记录一下心得. websocket是html5引入的一个新特性,传统的web应用是通过http协议来提供支持,如果要实时同步传输数据,需要轮询,效率低下 websocket是类 ...
- python websocket网页实时显示远程服务器日志信息
功能:用websocket技术,在运维工具的浏览器上实时显示远程服务器上的日志信息 一般我们在运维工具部署环境的时候,需要实时展现部署过程中的信息,或者在浏览器中实时显示程序日志给开发人员看.你还在用 ...
- Python websocket
一.自己实现websocket 网上流传的都是Python2的websocket实现 # coding=utf8 # !/usr/bin/python import struct, socket im ...
- 运维开发:python websocket网页实时显示远程服务器日志信息
功能:用websocket技术,在运维工具的浏览器上实时显示远程服务器上的日志信息 一般我们在运维工具部署环境的时候,需要实时展现部署过程中的信息,或者在浏览器中实时显示程序日志给开发人员看.你还在用 ...
- python websocket Django 实时消息推送
概述: WebSocket 是什么? WebSocket 是 HTML5 提供的一种浏览器与服务器间进行全双工通讯的协议.依靠这种协议可以实现客户端和服务器端 ,一次握手,双向实时通信. WebSoc ...
- python websocket 再线聊天室的 Demo
服务端 import tornado.web import tornado.ioloop import tornado.httpserver import tornado.options import ...
- python websocket 客户端连接
# -*- coding: utf-8 -*-import jsonimport websocketimport _thread as thread # try:# import thread# ex ...
- python websocket client 使用
import websocket ws = websocket.WebSocket() ws.connect("xx.xx.xx") ws.send("string&qu ...
- Python基于websocket实时通信的实现—GoEasy
Python websocket实时消息推送 在这里我记录一下之前如何实现服务器端与客户端实时通信: 实现步骤如下: 1. 获取GoEasy appkey. 在goeasy官网上注册一个 ...
随机推荐
- [redis] linux下安装篇(1)
一.redis是什么redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset(有 ...
- 下载与安装APache Cordova
最近老师留了写网页版或手机版程序,但先前没有好好听javaweb,而今年又没选Android移动应用开发.所以去图书馆借了一本书是关于HTML5+CSS3+jQueryMobile的. 这几天配置了打 ...
- ios程序后台继续运行
1.图标右上角显示消息个数 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { UIUserNotificati ...
- TCP建立连接与释放连接过程中的几个问题
TCP为何采用三次握手来建立连接,若采用两次握手可以吗,请说明理由? 不可以.采用三次握手是为了防止失效的连接请求报文段突然又传送到服务器,从而发生错误.当客户端发出的连接请求报文段由于某些原因没有及 ...
- java 父类的引用调用自己的属性 但是调用的方法必须是重写过的父类的方法 因为编译时候把他当作父类 运行时候才是他自己 所以必须重写父类得方法
- hive表信息查询:查看表结构、表操作等--转
原文地址:http://www.aboutyun.com/forum.PHP?mod=viewthread&tid=8590&highlight=Hive 问题导读:1.如何查看hiv ...
- liunx 用户和用户组的命令
查看用户列表 /etc/passwd 查看用户组列表 /etc/group 用户和用户组管理 groupadd groups 新增用户组 groupmod -n newgroupsr gro ...
- 在Linux上编译使用tcmalloc
项目需要使用tcmalloc,比较简单的方法是安装tcmalloc相关包(gpertools)后,将tcmalloc的静态库提取出来,在编译项目内核(执行makefile)时,链接上静态库即可. 这里 ...
- P3984 高兴的津津
题目描述 津津上高中了.她在自己的妈妈的魔鬼训练下,成为了一个神犇,每次参加一次OI比赛必拿Au虐全场.每次她拿到一个Au后就很高兴.假设津津不会因为其它事高兴,并且她的高兴会持续T天(包包含获奖当天 ...
- [洛谷P4626]一道水题 II
题目大意:求$lcm(1,2,3,\cdots,n)\pmod{100000007}$,$n\leqslant10^8$ 题解:先线性筛出质数,然后求每个质数最多出现的次数,可以用$\log_in$来 ...