使用Bottle实现websocket和http同端口复用
本帖最后由 arklearn 于 2020-7-22 08:16 编辑因为工作时候,有需求,同一个端口去接收websocket数据和http请求。
这个需求让我愁得掉了好些头发,没有办法硬着头皮去查资料。
一开始一发狠,用socket来做,反正http和websocket实际上也是一种socket,拼了。
后面发现脑袋大了,这是一个无底洞啊,时间有限,不符合python开发。pyhton里有那多框架,完全不用再造轮子。
突然,Bottle框架出现在我的眼前,忽如一夜春风来,千树万树梨花开,哈哈!!
bottle框架只是搭起了一个架子,实际websocket 还是用了gevent,这个用来解决websocket的。
from gevent.pywsgi import WSGIServer
from geventwebsocket import WebSocketError
from geventwebsocket.handler import WebSocketHandler
部分代码,附件里还加了线程:
'''
Bottle服务,绑定websocket和http服务
'''
class MyBottleServer(Bottle):
def __init__(self, ip="127.0.0.1", port=8737):
Bottle.__init__(self)
self.ip = ip
self.port = port
def __del__(self):
try:
if (self.server != None):
self.server.close_server()
except:
pass
def start_server(self):
self.server = WSGIServer((self.ip, self.port), self, handler_class=WebSocketHandler)
self.server.serve_forever()
def close_server(self):
if (self.server != None):
self.server.close()
self.server = None
def register_websocket_server(self):
@self.route('/wspost')
def handle_websocket():
wsock = request.environ.get('wsgi.websocket')
if not wsock:
abort(400, '此功能只能处理websocket')
message = ""
while True:
try:
if wsock.closed:
break
message = wsock.receive()
result = {
"flag": False,
"msg": ""
}
if message == None or message.strip() == "":
msg = u"获取websocket消息失败"
result["msg"] = msg
break
### 处理其他业务
if wsock.closed != True:
wsock.close()
break
except WebSocketError, ex:
logging.error(u"WebSocket异常信息")
logging.exception(ex)
# 如果异常报错,则断开连接
break
def register_http_server(self):
@self.route('/')
def index():
return template('<b>Hello {{name}}</b>!', name="xx")
@self.route('/datapost', method="POST")
def do_printform():
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS'
allow_headers = 'Referer, Accept, Origin, User-Agent'
response.headers[
'Access-Control-Allow-Headers'] = "Content-Type,Content-Length, Authorization, Accept,X-Requested-With"
response.content_type = "application/javascript; charset=utf-8"
message = request.params.get("message")
if message is None:
message = ""
try:
message = urllib.unquote(message);
except Exception, ex:
pass
##处理单据业务
time.sleep(5)
def register_error(self):
@self.error(404)
def error404(error):
return u'404'
def response_header(self):
# set cross headers
headers = {'Content-type': 'application/json'}
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS'
allow_headers = 'Referer, Accept, Origin, User-Agent'
headers['Access-Control-Allow-Headers'] = allow_headers
我把代码上传到附件里,去除工作所用的业务逻辑,只留下框架的实现,希望能给大家带来思路。
因为工作时间的关系,没有优化,感觉后面可以去掉bottle框架,只使用gevent框架。
页:
[1]