【发布时间】:2016-07-23 00:03:58
【问题描述】:
在 Qt 中实现一个简单的 HTTP 服务器,目的是将实时数据流式传输到 XMLHttpRequest 对象(AJAX/JavaScript)。
问题是设计模式需要通过套接字连接传输部分数据,将XHR中的readyState从'1'(Request)更改为'2'(Headers received),然后更改为'3'(Data收到) - 保持请求未决。这也称为“长轮询”或“彗星”,在大多数浏览器中都应该可以实现。
但是,它一直处于请求状态,直到连接关闭,然后接收到 readyState '2' 和 '4'。这对于 HTTP GET 来说是正常的,但对于这个应用程序来说是不需要的。
JavaScript:
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
console.log('readyState: ' + this.readyState + ' ' + this.status)
}
request.open("get", "localhost:8080/", true);
request.send();
Qt:
connect(socket, &QTcpSocket::readyRead, [=]()
{
QByteArray data = m_socket->read(1000);
socket->write("HTTP/1.1 200 OK\r\n");
socket->write("Content-Type: text/octet-stream\r\n");
socket->write("Access-Control-Allow-Origin: *\r\n");
socket->write("Cache-Control: no-cache, no-store, max-age=0, must-revalidate\r\n");
socket->flush();
}
所以最大的问题是:如何使 QtTcpSocket 下的网络系统在写入标头(以及随后的数据)后刷新待处理数据,而无需先断开连接? p>
附注:我最初是使用 WebSockets 实现的,但我必须使用的浏览器不支持。
编辑: HTTP 标头格式必须有一组额外的“\r\n”。现在可以了:
connect(socket, &QTcpSocket::readyRead, [=]()
{
QByteArray data = m_socket->read(1000);
socket->write("HTTP/1.1 200 OK\r\n");
socket->write("Content-Type: text/octet-stream\r\n");
socket->write("Access-Control-Allow-Origin: *\r\n");
socket->write("Cache-Control: no-cache, no-store, max-age=0, must-revalidate\r\n");
socket->write("\r\n");
socket->flush();
}
【问题讨论】:
-
这更像是一个 HTTP 问题。您确定通过网络发送的数据构成有效的 HTTP 回复吗?您是否将它们与来自符合要求的、正常工作的 HTTP 服务器的回复进行了比较?
-
这可能是 HTTP 标头问题,但我消除了它,因为它在
flush()之后执行disconnectFromHost()时有效,因此应该验证 HTTP 格式 - 至少在标准 GET 请求方面/回复。 -
您的
readyRead实现假定它将一次获得1000 个字节。这个假设是错误的,希望你真正的readyRead-attached 仿函数从任意大小的块中组装传入的数据;参见例如this answer 和另一个链接在其中。
标签: javascript qt http comet qtcpsocket