使用PHP-FPM和Apache时如何立即发送HTTP / 2标头

时间:2019-03-28 08:20:44

标签: php apache http-headers http2

当以FPM运行时,我似乎无法立即从PHP发送标头。它们仅在请求结束时与内容一起发送。

我有一个Apache + PHP-FPM安装程序。我在PHP和Apache中禁用了输出压缩。

我什至使用tcpdump -nn -i any -A -s 0 port 9000查看了TCP连接流,并且看到PHP直到最后才将标头发送给Apache,因此问题出在PHP设置上。

请参见下面我正在使用的测试代码。


header('Status: 200 OK');
header('Content-type: text/html; charset=utf-8');

header('Link: </src/app/src/App/Ui/Layout/default.css?__mtime=1553684041>; rel=preload; as=style;', false);

flush();

header('Test: 1', false);
sleep(5);
header('Test2: 2', false);

echo 'test';

我希望Link:标头在请求结束之前发送,即在'test'字符串之前发送,但不是。在5秒的延迟之后,所有标头均在请求结束时发送。

我在做什么错了?

1 个答案:

答案 0 :(得分:0)

默认情况下,#include <iostream> #include <WS2tcpip.h> #include <string> #include <sstream> #include <thread> #include <mutex> #include <list> #pragma comment (lib, "ws2_32.lib") using namespace std; class safe_queue { mutex m; list<string> str_queue; public: safe_queue() {}; void add(const string &s) { const lock_guard<mutex> lock(m); str_queue.push_back(s); } bool pop( string &s ) { const lock_guard<mutex> lock(m); if (!str_queue.empty()) { s = str_queue.front(); str_queue.pop_front(); return true; } return false; } }; int main() { // Initialze winsock WSADATA wsData; WORD ver = MAKEWORD(2, 2); int wsOk = WSAStartup(ver, &wsData); if (wsOk != 0) { cerr << "Can't Initialize winsock! Quitting" << endl; return 0; } // Create a socket SOCKET listening = socket(AF_INET, SOCK_STREAM, 0); if (listening == INVALID_SOCKET) { cerr << "Can't create a socket! Quitting" << endl; return 0; } // Bind the ip address and port to a socket sockaddr_in hint; hint.sin_family = AF_INET; hint.sin_port = htons(54000); hint.sin_addr.S_un.S_addr = INADDR_ANY; // Could also use inet_pton .... bind(listening, (sockaddr*)&hint, sizeof(hint)); // Tell Winsock the socket is for listening listen(listening, SOMAXCONN); // Create the master file descriptor set and zero it fd_set master; FD_ZERO(&master); // Add our first socket that we're interested in interacting with; the listening socket! // It's important that this socket is added for our server or else we won't 'hear' incoming // connections FD_SET(listening, &master); // this will be changed by the \quit command (see below, bonus not in video!) bool running = true; safe_queue sq; auto io_thread = thread([&] { string s; while (running && getline(std::cin, s, '\n')){ sq.add(s); } });//thread. while (running) { // Make a copy of the master file descriptor set, this is SUPER important because // the call to select() is _DESTRUCTIVE_. The copy only contains the sockets that // are accepting inbound connection requests OR messages. // E.g. You have a server and it's master file descriptor set contains 5 items; // the listening socket and four clients. When you pass this set into select(), // only the sockets that are interacting with the server are returned. Let's say // only one client is sending a message at that time. The contents of 'copy' will // be one socket. You will have LOST all the other sockets. // SO MAKE A COPY OF THE MASTER LIST TO PASS INTO select() !!! fd_set copy = master; timeval tv = {0,0}; // See who's talking to us int socketCount = select(0, &copy, nullptr, nullptr, &tv); for (int i = 0; i < socketCount; i++) { //Accept a new connection SOCKET sock = copy.fd_array[i]; if (sock == listening) { //Accept a new connection SOCKET client = accept(listening, nullptr, nullptr); //Add a new connection FD_SET(client, &master); string mssg = "Welcome to the awesome chat server\n"; //Send a welcome message to the connected client send(client, mssg.c_str(), mssg.size() + 1, 0); } }//for. string mssg; if (sq.pop(mssg) ) { std::cout << "Send :" << mssg << endl; for (u_int i = 0; i < master.fd_count; i++) { SOCKET outsock = master.fd_array[i]; if (outsock != listening) { send(outsock, mssg.c_str(), mssg.size() + 1, 0); } } } }//while // Remove the listening socket from the master file descriptor set and close it // to prevent anyone else trying to connect. FD_CLR(listening, &master); closesocket(listening); // Message to let users know what's happening. string msg = "Server is shutting down. Goodbye\r\n"; while (master.fd_count > 0) { // Get the socket number SOCKET sock = master.fd_array[0]; // Send the goodbye message send(sock, msg.c_str(), msg.size() + 1, 0); // Remove it from the master file list and close the socket FD_CLR(sock, &master); closesocket(sock); } // Cleanup winsock WSACleanup(); system("pause"); return 0; } 设置为fastcgi_buffering

您需要在相关的on块中添加:fastcgi_buffering off;