1、背景

最近有个项目,需要搭建一个socket服务器,一个web服务器,然后实现两个服务器之间的通讯交互。刚开始的方案是用Python中socket模块实现一个多线程的socket服务器,然后用Flask实现一个web服务器,他们之前通过线程交互实现通讯。

但是在我看来这个方案有例外一个更好的解决方法,就是用Torndao框架。鉴于网上用Tornado实现一个程序同时实现web服务和socket服务器并且实现交互的文章几乎没有,所以记录一下。觉得写得好麻烦点个赞,写得不好请指出,有疑问可以留言。

2、准备

2.1、环境部署

Python3.x

pip3 install Tornado

2.2、目录结构

目录结构如上图,这个目录结构包括文件命名只是我的个人习惯。其实目录结构不固定,只要合理就行。另外,原本项目是前后分离的只需要实现API接口,所以我这里就没有涉及到HTML的东西。

3、服务器的实现

3.1、Socket服务器实现

socket服务器部分实现主要靠 Tornado中的TCPServer类

3.1.1、 导入类

socket_server.py:

from tornado.iostream import IOStream # 这句可以没有,只是作为参数的代码提示

from tornado.tcpserver import TCPServer

3.1.2、 构建一个Connecter类

socket_server.py:

class Connecter:

clients = set() # 存放连接的客户端

async def init(self, stream: IOStream, address: tuple):

"""

注意这个不是构造方法,这里不用构造方法是为了方便后续的与web端相互通信

"""

self.stream, self.address = stream, address

self.clients.add(self)

print("{address} 上线!".format(address=address))

self.stream.set_close_callback(self.onClose) # 客户端离线的时候会被调用

await self.receive() # 接受消息

async def receive(self):

"""

接受消息

"""

while True:

try: # 因为异步的原因。可能设备离线后还在接收消息,所以try一下,不让错误打印出来,其实打印了错误也不影响程序运行

data = await self.stream.read_bytes(num_bytes=1024, partial=True) # num_bytes:每次最多接收字节,partial:数据中断后视为接收完成

print(data)

# TODO:接收到数据的处理

except:

pass

def send(self, data):

"""

发送消息

:param data: 消息内容

"""

self.stream.write(bytes(data.encode('utf8')))

def onClose(self):

"""

客户端离线

"""

print("{address} 离线!".format(address=self.address))

self.clients.remove(self) # 在clients内删掉该客户端

3.1.3、 构建一个SocketServer类

socket_server.py:

class SocketServer(TCPServer): # 需要继承TCPServer这个类

async def handle_stream(self, stream: IOStream, address: tuple): # 实现类里面的handle_stream方法

await Connecter().init(stream, address) # 每次有客户端连入都实例化一个Connecter类

3.2、Web服务器实现

3.2.1、 实现一个requestHandler

web_test.py:

from tornado.web import RequestHandler # 导入RequestHandler类

class TestApiHandler(RequestHandler): # 继承RequestHandler类

def get(self): # 实现GET方法,GET请求会执行这个方法

pass

def post(self): # 实现POST方法,POST请求会执行这个方法

pass

3.2.2、 实现web app

web_server.py:

from tornado.web import Application # 导入Tornado的Application类

from .src.web_test import TestApiHandler # 导入我们自己写的TestApiHandler类

def webServerApp(): # 构造出webApp

return Application([

(r'/api_test/', TestApiHandler), # 把/api_test/路由到TestApiHandler

])

3.3、程序入口

3.3.1、 导入web_server和socket_server,还有导入tornado的ioloop

main.py:

from web_server.web_server import webServerApp

from socket_server.socket_server import SocketServer

from tornado import ioloop

from tornado.options import define, options

3.3.2、 定义默认端口

main.py

#这里用define定义端口,可以方便使用命令行参数的形式修改端口

define("socketPort", 8888, type=int) # socket默认使用8888端口

define("webPort", 8080, type=int) # web默认使用8080端口

3.3.3、 启动代码

main.py

def main():

socket_server = SocketServer()

socket_server.listen(options.socketPort, '0.0.0.0')

print("socket服务器启动,端口:{port}".format(port=options.socketPort))

app = webServerApp()

app.listen(options.webPort, '0.0.0.0')

print("web服务器启动,端口:{port}".format(port=options.webPort))

ioloop.IOLoop.current().start()

if __name__ == '__main__':

main()

4、服务器运行效果

到此,一个混合型的socket+web服务器已经搭建好了。我们我们运行main.py文件可以看到打印的信息,socket和web都正常运行。

我在这里简单地写了一个socket客户端测试,代码如下:

import socket

import datetime

class Client:

def __init__(self):

with socket.create_connection(("127.0.0.1", 8888)) as sock:

while True:

msg = sock.recv(1024)

if len(msg) > 0:

print(msg)

sock.send(bytes(str(datetime.datetime.now).encode('utf8')))

msg = []

if __name__ == "__main__":

Client()

可以看到tornado异步的形式实现了多客户端同时接入socket。同时也可以测试web接口是正常的,如下图:

5、Web服务器与Socket服务器交互

重点来了,web和socket怎样实现交互呢?其实很简单。

5.2、 web >> socket

web_test.py -> TestApiHandler -> post:

5.2.1、 导入Connecter类

from socket_server.socket_server import Connecter

5.2.2、 实现请求接口发送消息到socket客户端

def post(self): # 实现POST方法,POST请求会执行这个方法

msg = self.get_argument("msg") # 得到post请求中的msg的值

ip = self.get_argument('ip') # 得到要发送的ip

c = Connecter() # 实例化Connecter类

counter = 0 # 记录发送到客户端的个数

for client in c.clients: # type:Connecter

if client.address[0] == ip: # 根据ip发送

client.send(msg) # 发送消息

counter += 1 # 计数加1

self.write("{'send_counter':" + str(counter) + "}")

5.2.3、 效果

请求接口可以返回数据,已经成功发送一个客户端

客户端也能收到消息:

5.1、 socket >> web

其实socket发送的消息让web马上收到消息是不太现实的,但是我们可以把数据保存起来(可以是数据库、全局变量、缓存……),然后通过api接口再把数据取出。另外还有一种方法是通过socket和websocket进行交互通讯,这种方法是推荐的方法,同样的也可以用Tornado去实现,感兴趣可以去研究一下也很简单。如何有需要我提供socket、websocket、web三个端都互相交互的例子可以留言。

这里为了简单一点,我使用一个类作为全局变量来保存数据,然后用接口访问,拿出这个类的值来演示一下效果。

5.1.1、 声明类作为全局变量

socket_data_processing.py

class SocketData:

msg = ""

5.1.2、 接受到的消息保存到这个类里面的msg

socket_server.py -> Connecter -> receive

async def receive(self):

"""

接受消息

"""

while True:

try: # 因为异步的原因。可能设备离线后还在接收消息,所以try一下,不让错误打印出来,其实打印了错误也不影响程序运行

data = await self.stream.read_bytes(num_bytes=1024, partial=True) # num_bytes:每次最多接收字节,partial:数据中断后视为接收完成

print(data)

from .src.socket_data_processing import SocketData

SocketData.msg = data.decode('utf8')

except:

pass

5.1.3、 用get方法显示socket显示回来的数据

web_test.py -> TestApiHandler -> get:

def get(self): # 实现GET方法,GET请求会执行这个方法

from socket_server.src.socket_data_processing import SocketData

self.write(SocketData.msg)

5.1.4、 效果

可以看到,从socket传过来的字符串,被我通过Api读取到了。

到此这篇关于Python Tornado实现WEB服务器Socket服务器共存并实现交互的方法的文章就介绍到这了,更多相关Python  WEB服务器Socket服务器共存交互内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

python tornado websocket_Python Tornado实现WEB服务器Socket服务器共存并实现交互的方法...相关推荐

  1. python tornado websocket_python tornado websocket 多聊天室(返回消息给部分连接者)

    1 #-*-coding:utf-8-*- 2 __author__ = 'zhouwang' 3 importjson4 importtornado.web5 importtornado.webso ...

  2. Java网络编程——9.服务器Socket

    2019独角兽企业重金招聘Python工程师标准>>> 前一章从客户端的角度讨论了Socket,客户端就是向监听连接的服务器打开一个Socket的程序,不过如果不能与服务器对话,客户 ...

  3. nginx tornado php,tornado+nginx+python 微信公众号接入配置

    配置环境:腾讯主机 Ubuntu Server 16.04.1 LTS 64位 需要用到的软件或者包:nginx,tornado框架 xshell6(非必需) 微信公众号测试平台:http://mp. ...

  4. 简易有WEB文件服务器,Python实现简易版的Web服务器(推荐).pdf

    Python实实现现简简易易版版的的Web服服务务器器(推推荐荐) 下面给大家介绍python实现简易版的web服务器,具体内容详情大家通过本文学习 ! 1.请自行了解HTTP协议 /article/ ...

  5. python模块介绍-Tornado:Tornado中文文档-概述

    2019独角兽企业重金招聘Python工程师标准>>> 快速链接 tornado-4.1.tar.gz, tornado最新版本 tornado源码@github 邮件列表:讨论.最 ...

  6. 用python写一个简单的web服务器

    人生苦短,我用python 简洁高效,这才是理想的语言啊 分享一点python的学习经验-----如何用python写一个简单的web服务器 首先,我们需要简单地了解一下网络通信协议,这里用白话介绍一 ...

  7. 用Python建立最简单的web服务器

    用Python建立最简单的web服务器 利用Python自带的包可以建立简单的web服务器.在DOS里cd到准备做服务器根目录的路径下,输入命令: python -m Web服务器模块 [端口号,默认 ...

  8. 通过python建立一个web服务查看服务器上的文本、图片、视频等文件

    通过python建立一个web服务查看服务器上的文本.图片.视频等文件 文章目录: 1 在服务器端开启一个服务 2 在本地浏览器中输入服务器的ip地址 1 在服务器端开启一个服务 python -m ...

  9. python socket服务器_python网络编程学习笔记(三):socket网络服务器

    1.TCP连接的建立方法 客户端在建立一个TCP连接时一般需要两步,而服务器的这个过程需要四步,具体见下面的比较.步骤 TCP客户端 TCP服务器 第一步 建立socket对象 建立socket对象 ...

最新文章

  1. plotly可视化绘制双子图(subplots)
  2. 因为权限缺乏导致SAP CRM AET字段删除失败
  3. 调整Tomcat上的参数提高性能[转]
  4. php 汉字分割,php支持中文字符串分割的函数
  5. Mr.J-- jQuery学习笔记(十三)--选项Tab卡
  6. Python爬虫Scrapy入门
  7. php对接建行h5网页支付
  8. 各种笔记本进入BIOS的快捷键
  9. 17美亚团队赛电子取证
  10. 【航线运输驾驶员理论考试】飞行原理
  11. Mac电脑如何实现Word一键转PPT
  12. APP - 朋友圈广告原来是可以关掉的
  13. 小说阅读大全(安卓)最后一个绿色版。
  14. Chrome 制作绿色便携版
  15. SQLServer2008密钥
  16. 虚拟化服务器拓扑结构图,6-4简单虚拟化数据中心拓扑图介绍
  17. 2020-02-25
  18. unity 标准资源包中的围绕旋转摄像机
  19. stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
  20. 收获荣誉证书,显摆一下

热门文章

  1. 写给小白的WordPress详细安装步骤
  2. 强化学习ppt_强化学习和最优控制的十个关键点81页PPT汇总
  3. leetcode 高薪_利用两种不同的方法解LeetCode第1312题:让字符串成为回文串的最少插入次数
  4. 【java基础知识】linux运行或停止jar包程序
  5. day29 java 的IO流(2)
  6. oracle怎么定时执行存储过程6,Oracle中如何定时调用存储过程
  7. wireshark网络分析就这么简单 pdf_用了这么久才发现!原来PDF提取文字这么简单,看完涨知识了...
  8. python实现两个接口的依赖关系
  9. mqtt 获取 状态_MQTT设备接入及上报数据的命令行模拟器(Java)
  10. python查找指定文件夹_python实现在目录中查找指定文件的方法