user2292759
user2292759

Reputation: 159

Properly sending HTTP response over sockets

I have a sockets app, and want to allow browsers to send/receive data. Unfortunately, for some odd reason, this code just will not work for Chrome, nor curl. What is strange though, is it seems to work almost perfectly fine with Internet Explorer Edge, and even some REST playgrounds available on the internet.

What could be the cause of this? I want to assume it's something to do with headers, but, I sent headers exactly matching another domain, and still, it stalls.

What seems to happen is Chrome loads the data, but, stalls, and an official response is never received -- or maybe it just never finished? I can see all text on the page, however, google is still loading, and the "Server Response" reports that it received nothing. In addition to that, I think it's sending the same response to a client twice.

Here is my code:

// 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;
}

Upvotes: 1

Views: 1086

Answers (2)

kvr
kvr

Reputation: 573

What seems to happen is Chrome loads the data, but, stalls

As you mentioned it 'stalls', looking at your code, you are calling 'recv', which is a blocking call. If there is no data available, recv will block.

Could this be where you are stalling? There are APIs available to check if there is data available first, to allow you to avoid blocking conditions. Just mentioning this incase it helps.

If you make it to the 'send()', I doubt you'd stall, but that too could be possible.

Upvotes: 1

Steffen Ullrich
Steffen Ullrich

Reputation: 123531

You are setting a huge Content-length of 18076 but your content is much much smaller. Thus the browser will wait for more content. But instead of providing more content you simply wait for the browser to send another request and thus both client and server are waiting for each other.

Apart from that lots of headers you send make no sense: Accept, Accept-Encoding, Accept-Language and Host are all headers which are relevant for the request and make no sense in the response. And the proper line ending with HTTP is \r\n and not \n although browsers usually don't care about this detail.

Upvotes: 1

Related Questions