为什么这款最小的HTTP测试服务器在一半的时间内失败了?

发布于 2025-02-11 04:48:41 字数 1331 浏览 2 评论 0原文

我正在尝试在Windows上写最小的HTTP服务器,并使用 http://127.0.0.0.1/5000 。有时以下代码有时起作用(“ Hello World”),但是请求在Chrome中使用err_connection_aborted(即使在我重新启动服务器之后)失败了一半。为什么?

错误:

#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
int main()
{
    WSADATA WSAData;
    SOCKET sock, csock;
    SOCKADDR_IN sin, csin;
    WSAStartup(MAKEWORD(2,0), &WSAData);
    sock = socket(AF_INET, SOCK_STREAM, 0);
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5000);
    bind(sock, (SOCKADDR *) &sin, sizeof(sin));
    listen(sock, 0);
    while(1)
    {
        int sinsize = sizeof(csin);
        if((csock = accept(sock, (SOCKADDR *) &csin, &sinsize)) != INVALID_SOCKET)
        {
            std::string response = "HTTP/1.1 200 OK\nConnection: close\nContent-Length: 11\n\nHello World";
            send(csock, response.c_str(), response.size(), 0);
            std::cout << "done";
            closesocket(csock);
        }
    }
    return 0;
}

I'm trying to write a minimal HTTP server on Windows and see the response in Chrome with http://127.0.0.1/5000. The following code works sometimes ("Hello World"), but the request fails half of the time with ERR_CONNECTION_ABORTED in Chrome (even after I restart the server). Why?

Error:

enter image description here

#include <winsock2.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")
int main()
{
    WSADATA WSAData;
    SOCKET sock, csock;
    SOCKADDR_IN sin, csin;
    WSAStartup(MAKEWORD(2,0), &WSAData);
    sock = socket(AF_INET, SOCK_STREAM, 0);
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5000);
    bind(sock, (SOCKADDR *) &sin, sizeof(sin));
    listen(sock, 0);
    while(1)
    {
        int sinsize = sizeof(csin);
        if((csock = accept(sock, (SOCKADDR *) &csin, &sinsize)) != INVALID_SOCKET)
        {
            std::string response = "HTTP/1.1 200 OK\nConnection: close\nContent-Length: 11\n\nHello World";
            send(csock, response.c_str(), response.size(), 0);
            std::cout << "done";
            closesocket(csock);
        }
    }
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夕色琉璃 2025-02-18 04:48:41

在关闭连接之前,您无法阅读客户端的请求。这通常会导致服务器将第一个发送回客户端,这可能会导致err_connection_abort在处理响应本身之前对其进行处理时。

正如另一个(已删除)答案所观察到的那样,可以通过在连接关闭之前添加一些较短的延迟来“减轻”这一点,从而使响应由客户端处理。

不过,正确的解决方法是阅读客户的请求。

除此之外,您的响应无效HTTP,因为您使用\ n而不是\ r \ n作为行端和标头结束。


工作解决方案:

#include <winsock2.h>
#include <iostream>
#define DEFAULT_BUFLEN 8192
#pragma comment(lib, "ws2_32.lib")
int main()
{
    char recvbuf[DEFAULT_BUFLEN];
    WSADATA WSAData;
    SOCKET sock, csock;
    SOCKADDR_IN sin, csin;
    WSAStartup(MAKEWORD(2,0), &WSAData);
    sock = socket(AF_INET, SOCK_STREAM, 0);
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5000);
    bind(sock, (SOCKADDR *) &sin, sizeof(sin));
    listen(sock, 0);
    while (1) 
    {
        int sinsize = sizeof(csin);
        if ((csock = accept(sock, (SOCKADDR *) &csin, &sinsize)) != INVALID_SOCKET)
        {
            recv(csock, recvbuf, DEFAULT_BUFLEN, 0);
            std::string response = "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Length: 11\r\n\r\nHello World";
            send(csock, response.c_str(), response.size(), 0);
            std::cout << "done";
            closesocket(csock);
        }
    }
    return 0;
}

You fail to read the client's request before closing the connection. This usually results in the server sending a RST back to the client, which can cause the ERR_CONNECTION_ABORTED when it is processed before the response itself was processed.

As observed by another (deleted) answer, this can be "mitigated" by adding some short delay before the connection is closed, so that the response is processed by the client.

The right fix is to read the request from the client, though.

Apart from that, your response is not valid HTTP since you use \n instead of \r\n as line end and header end.


Working solution:

#include <winsock2.h>
#include <iostream>
#define DEFAULT_BUFLEN 8192
#pragma comment(lib, "ws2_32.lib")
int main()
{
    char recvbuf[DEFAULT_BUFLEN];
    WSADATA WSAData;
    SOCKET sock, csock;
    SOCKADDR_IN sin, csin;
    WSAStartup(MAKEWORD(2,0), &WSAData);
    sock = socket(AF_INET, SOCK_STREAM, 0);
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(5000);
    bind(sock, (SOCKADDR *) &sin, sizeof(sin));
    listen(sock, 0);
    while (1) 
    {
        int sinsize = sizeof(csin);
        if ((csock = accept(sock, (SOCKADDR *) &csin, &sinsize)) != INVALID_SOCKET)
        {
            recv(csock, recvbuf, DEFAULT_BUFLEN, 0);
            std::string response = "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Length: 11\r\n\r\nHello World";
            send(csock, response.c_str(), response.size(), 0);
            std::cout << "done";
            closesocket(csock);
        }
    }
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文