我有一台服务器,只需几分钟即可处理特定请求,然后对其进行响应。
客户端必须等待响应,而不知道何时完成。
有没有办法让客户知道处理状态? (比如50%完成,80%完成),客户不需要轮询状态。
答案 0 :(得分:11)
不使用任何较新的技术(websockets,webpush / http2,...),我之前使用过简化的 Pushlet 或长轮询解决方案1.1和各种javascript或自己的客户端实现。如果我的解决方案不适合您的使用案例,您可以随时使用这两个名称来查找更多可能的方法。
<强>客户端强> 发送请求,读取17个字节(Inital http响应),然后一次读取2个字节,获得处理状态。
服务器强> 发送有效的HTTP响应,并在请求进度期间发送完成2个字节的百分比,直到最后2个字节为“ok”并关闭连接。
更新:示例uwsgi server.py
from time import sleep
def application(env, start_response):
start_response('200 OK', [])
def working():
yield b'00'
sleep(1)
yield b'36'
sleep(1)
yield b'ok'
return working()
更新:示例请求client.py
import requests
response = requests.get('http://localhost:8080/', stream=True)
for r in response.iter_content(chunk_size=2):
print(r)
示例服务器(仅用于测试:)
import socket
from time import sleep
HOST, PORT = '', 8888
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)
while True:
client_connection, client_address = listen_socket.accept()
request = client_connection.recv(1024)
client_connection.send('HTTP/1.1 200 OK\n\n')
client_connection.send('00') # 0%
sleep(2) # Your work is done here
client_connection.send('36') # 36%
sleep(2) # Your work is done here
client_connection.sendall('ok') # done
client_connection.close()
如果最后2个字节不是“ok”,则在其他地方处理错误。这不是很好的HTTP状态代码合规性,而是多年前对我有用的解决方法。
telnet客户端示例
$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.1 200 OK
0036okConnection closed by foreign host.
答案 1 :(得分:2)
使用 Chunked Transfer Encoding ,这是一种传输未知长度流的标准技术。
请参阅:Wikipedia - Chunked Transfer Encoding
这里有一个python服务器实现,可以作为GitHub上的要点:
它使用标准库模块
使用分块传输编码发送内容在客户端中,如果服务器已通知分块传输编码,则您只需:
import requests
response = requests.get('http://server.fqdn:port/', stream=True)
for r in response.iter_content(chunk_size=None):
print(r)
chunk_size=None
,因为这些块是动态的,并且将由分块传输语义的简单约定中的信息确定。
请参阅:http://docs.python-requests.org/en/master/user/advanced/#chunk-encoded-requests
当您在回复内容100
中看到r
时,您知道在处理100
后,下一个块将是实际内容。
答案 2 :(得分:2)
This answer probably won’t help in your particular case, but it might help in other cases.
The HTTP protocol supports informational (1xx) responses:
indicates an interim response for communicating connection status or request progress prior to completing the requested action and sending a final response
There is even a status code precisely for your use case, 102 (Processing):
interim response used to inform the client that the server has accepted the complete request, but has not yet completed it
Status code 102 was removed from further editions of that standard due to lack of implementations, but it is still registered and could be used.
So, it might look like this (HTTP/2 has an equivalent binary form):
HTTP/1.1 102 Processing
Progress: 50%
HTTP/1.1 102 Processing
Progress: 80%
HTTP/1.1 200 OK
Date: Sat, 05 Aug 2017 11:53:14 GMT
Content-Type: text/plain
All done!
Unfortunately, this is not widely supported. In particular, WSGI does not provide a way to send arbitrary 1xx responses. Clients support 1xx responses in the sense that they are required to parse and tolerate them, but they usually don’t give programmatic access to them: in this example, the Progress
header would not be available to the client application.
However, 1xx responses may still be useful (if the server can send them) because they have the effect of resetting the client’s socket read timeout, which is one of the main problems with slow responses.