通过套接字正确发送HTTP响应

时间:2016-02-21 20:20:55

标签: c++ sockets

我有一个套接字应用,并希望允许浏览器发送/接收数据。不幸的是,由于一些奇怪的原因,这段代码不适用于Chrome,也不适用于卷曲。但奇怪的是,它似乎与Internet Explorer Edge几乎完全一致,甚至可以在互联网上使用一些REST游乐场。

这可能是什么原因?我想假设它与标题有关,但是,我发送的标题与另一个域完全匹配,但它仍然停滞不前。

似乎发生了什么事情,Chrome会加载数据,但是,停止,并且从未收到官方回复 - 或者它可能从未完成?我可以看到页面上的所有文字,但谷歌仍在加载,并且“服务器响应”"报告说它什么也没收到。除此之外,我认为它会向客户发送两次相同的响应。

这是我的代码:

// sockserver.cpp : Defines the entry point for the console application.
//

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <process.h>
#include <stdio.h>
#include <map>
#pragma comment(lib,"ws2_32.lib" )

unsigned int __stdcall  ServClient(void *data);

int main(int argc, char* argv[])
{

    WSADATA wsaData;
    int iResult;
    sockaddr_in addr;
    SOCKET sock, client;

    addr.sin_family = AF_INET;
    addr.sin_port = htons(5900);
    addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.22");

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);//2.2 

    if (iResult)
    {
        printf("WSA startup failed");
        return 0;
    }


    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (sock == INVALID_SOCKET)
    {
        printf("Invalid socket");
        return 0;
    }

    iResult = bind(sock, (sockaddr*)&addr, sizeof(sockaddr_in));

    if (iResult)
    {

        printf("bind failed %u", GetLastError());

        return 0;
    }

    iResult = listen(sock, SOMAXCONN);

    if (iResult)
    {

        printf("iResult failed %u", GetLastError());

        return 0;
    }

    while (client = accept(sock, 0, 0))
    {
        if (client == INVALID_SOCKET)
        {
            printf("invalid client socket", GetLastError());
            continue;
        }
        _beginthreadex(0, 0, ServClient, (void*)&client, 0, 0);

    }


    return 0;
}

std::map<int, SOCKET> sockList;
unsigned int __stdcall ServClient(void *data)
{
    SOCKET* client = (SOCKET*)data;
    SOCKET Client = *client;
    printf("Client connected\n");

    int xx = 0;

    char chunk[200];
    while (recv(Client, chunk, 200, 0))
    {

        char buf[] = "HTTP/1.1 200 OK\nContent-Type: text/html\nAccept: */*;Date:Sun, 21 Feb 2016 18:26:33 GMT\nServer: ubersnip\nContent-Length:18076\nAccept-Encoding:gzip, deflate, sdch\nAccept-Language:en-US,en;q=0.8\nCache-Control:max-age=0\nConnection:keep-alive\nHost:localhost:2222\nSet-Cookie:acct=t=t%2flE8KL9jDBOed05o1eMDiINlDfMvLxp&s=CUBOpXFMXmBt4u3pf%2fx5efr5WWkyGT3U; domain=.stackoverflow.com; expires=Sun, 21-Aug-2016 18:26:33 GMT; path=/; HttpOnly\n\n<html><body>Hello World</body></html>";

        //sockList[sockList.size()] = Client;
        send(Client, buf, strlen(buf), 0);
        /*if (xx >= 1) {
            closesocket(Client);
            return 1;
        }
        else {
            xx++;
        }*/
        printf("%s \t %d\n", chunk, GetCurrentThreadId());
    }
    return 0;
}

2 个答案:

答案 0 :(得分:1)

您设置的内容长度为18076,但内容要小得多。因此浏览器将等待更多内容。但是,不是提供更多内容,而是等待浏览器发送另一个请求,因此客户端和服务器都在等待彼此。

除了你发送的大量标题之外没有意义:Accept,Accept-Encoding,Accept-Language和Host都是与请求相关的标题,在响应中没有意义。以HTTP结尾的正确行是\r\n而不是\n,尽管浏览器通常不关心此细节。

答案 1 :(得分:1)

  

Chrome似乎会加载数据,但停止

正如你提到的那样'停顿',看着你的代码,你正在调用'recv',这是一个阻塞调用。如果没有可用数据,则recv将阻止。

这可能是你拖延的地方吗?有一些API可用于检查是否有数据可用,以避免阻塞条件。只要提一下它就会有所帮助。

如果你进入'发送()',我怀疑你是否会失速,但这也是可能的。