赞
踩
想在flask编写的服务器程序实现这样一个功能,与底层硬件通信。底层硬件是网络接口,通过TCP/UDP协议进行数据传输。因此服务器需要使用socket。然而flask的socket是websocket,它虽然从socket衍生出来,但仅用于与客服端进行数据交互。怎么办?
@socketio.on('needdata')
def onNeeddata():
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#建立一个socket
sock.connect(hardware_addr)#连接到硬件
sock.send(cmd)#向硬件发送指令
data=sock.recv(1024)#接收硬件的数据
socketio.emit("givedata",data)#发给客户端
对于上图中的通信B很容易搞定,下面主要是解决通信A的问题。
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#新建socket
sock.bind(address)#绑定地址
sock.listen(30)
connection, addr=sock.accept()#等待客户端发送消息,此时程序阻塞在这,如果收到消息会往下执行。
msg=connection.recv(1024)#通过新生成的connection来接收消息,connection也是一个socket
connection.sendto(data,client_address)#通过新生成的connection来发送数据
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)#新建socket sock.setblocking(False)#设置成非阻塞 sock.bind(address)#绑定地址 sock.listen(30) CLIENT=[]#客户的列表 while True: if stop():#退出循环 break try: connection, addr=sock.accept() CLIENT.append((connection,addr)) except BlockingIOError:#有阻塞异常,可以pass掉 pass for c_socket,c_addr in client_list: try: msg=c_socket.recv(1024)#接收数据 except (BlockingIOError, ConnectionResetError): pass c_socket.sendto(data,c_addr )#发送数据 #清理连接到客户端的socket for c_socket,c_addr in client_list: c_socket.close() client_list.remove((c_socket,c_addr)) sock.close()#关闭服务器的socket
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False)#设置成非阻塞 CLIENT=[] app=Flask(__name__) #连接线程 def connect(): while True: if stop(): break try: connection, addr=sock.accept() CLIENT.append((connection, addr)) print("接收到新模块 其地址为:",addr,"目前模块有",len(CLIENT),"个") except BlockingIOError: pass def receive(): while True: if stop(): break for c_socket,c_addr in CLIENT: try: msg=c_socket.recv(1024) except (BlockingIOError, ConnectionResetError): pass @app.route('/') def index(): sock.bind(server_address) sock.listen(30) heartbeat() connect_run=threading.Thread(target=connect)#连接客户端线程 receive_run=threading.Thread(target=receive)#接收数据线程 connect_run.start()#启动连接客户端线程 receive_run.start()#启动接收数据线程 return render_template('index.html') #开启flask服务器 if __name__=="__main__": socketio.run(app, debug=True, host=SERVER_IP, port=SERVER_PORT) for c_socket,c_addr in CLIENT: c_socket.close() CLIENT.remove((c_socket,c_addr)) sock.close()
需要注意的是socket的bind函数和listen函数必须在flask里面的某个路径函数里,如果放在开启flask前面就开启线程,则flask无法开启,具体原因正在查明
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。