带WWW-Authenticate头的HTTP 401响应会关闭连接吗?
我开发了一个客户端-服务器架构的程序,当客户端向localhost:25000发送GET请求时,服务器返回包含WWW-Authenticate头的401状态码响应。以下是服务器处理请求并发送401消息的代码:
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); //TODO: accept connection //TODO: send 401 message and authentificate user //close connection char buffer[9000]; int bytes = 0; bytes = recv(newsockfd, buffer, 1500, 0); char message[] = "HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm='localhost'\r\nContent-Type: text/html;\r\n\r\n"; int length = strlen(message); while (length > 0) { printf("send bytes : %d\n", bytes); bytes = send(newsockfd, message, length, 0); if(bytes==-1){ continue; } length = length - bytes; } char parser[5] = "Basic"; int flag = 0; int received = 0; printf("Token : %s , tokensize : %d\n", token, tokensize); char c; bytes = 0; // shutdown(newsockfd, SHUT_RDWR); // close(newsockfd); // newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); bytes = recv(newsockfd, buffer, 1500, 0);
问题在于,当我两次调用recv时(最后一行),recv始终返回0,说明连接已关闭。我使用的是HTTP/1.1和BSD Socket,原本认为应该支持持久连接。但取消注释关闭连接并重新accept的代码后,程序运行正常。请问:带WWW-Authenticate头的响应会关闭连接吗?
回答
不是WWW-Authenticate头导致连接关闭,问题出在你的HTTP响应缺少持久连接相关的头字段,客户端在收到401响应后主动关闭了连接。
HTTP/1.1默认支持持久连接,但前提是双方明确维持连接的意图。如果你的响应没有告知客户端“连接可以保持打开”,客户端会默认关闭连接。
你需要在401响应中添加以下头字段之一:
Connection: keep-alive:明确告知客户端保持连接Content-Length: 0:因为你的响应体为空,这个头能让客户端明确知道响应已结束,不会直接关闭连接
当前你的响应仅返回状态行、WWW-Authenticate和Content-Type头,没有任何连接存活的提示。客户端收到这类HTTP/1.1响应后,会判定服务器无维持连接的意愿,于是主动关闭TCP连接,这就是第二次recv返回0的原因。
另外还有个细节:你发送响应的循环里,printf("send bytes : %d\n", bytes);中的bytes是之前recv的结果,并非本次send的字节数,属于日志错误,但不影响连接逻辑。
当你取消注释关闭连接再重新accept的代码时,相当于每次请求都使用新连接,匹配了客户端关闭连接后的行为,所以程序能正常运行。
内容的提问来源于stack exchange,提问作者omegafrog

