(GET HTTP Request) C++ sockets using winsock.h

2019-08-15 09:02发布

问题:

Okay, before anyone jumps to conclusions (and do to the fact of me keeping this relevant to others), basically, I'm trying to make a Get Request with sockets in C/C++ using Winsock.h.
[Main problem existing in running of the SocketRequest Function]
I've been getting error response codes anywhere from: "WSAENOTCONN 10057" to "WSAENOTSOCK 10038" which, I found more information on that here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx

Now, this is going to be a little irrelevant to others, but more to my situation. I'm trying to implement this on an XBOX360 Devkit, using "winsockx.h" and it crashes when I make a "SocketRequest"... here's the code WITH output for debugging purposes. (I understand this isn't normally what you'd see, so take it how you want)

Here's the included files:

#include "stdafx.h"
#include <time.h>
#include "Hooks.h"
#include <xhttp.h>
#include <winsockx.h>
#include <iostream>
#include <xtl.h>
#include <xbdm.h>
#include <malloc.h>
#include <stdio.h>

Here's the definitions and instances:

int Socket;
struct sockaddr_in SocketAddress;
char bufferReturn[10000];
char serverAddr[2000];
bool returnTEST = false;
char *Request1;
char *Request2;
char *ResetRequest;
//http://www.cplusplus.com/forum/general/9403/
//http://www.cplusplus.com/forum/beginner/139313/

#define SERVER_PORT htons(80)

Here's the code (Including the SocketRequest function that fails to run):

char* SocketRequest(char* URL, char* Path = "")
{
//THIS IS THE FUNCTION THAT CRASHES WHEN IT'S CALLED IDK WHY... NOTHING IN HERE RUNS, NOT EVEN THE "prinf" STATEMENT. 
    printf( "Step 0");
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("WSA Startup FAILED! ", WSAGetLastError() );
    }
    printf( "Step 1");
    SocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    printf( "Step 2");
    SocketAddress.sin_family = AF_INET;
    printf( "Step 3");
    SocketAddress.sin_port = SERVER_PORT;
    printf( "Step 4");
    Socket = socket(AF_INET, SOCK_STREAM, 0);

    printf( "Step 5");
    // Make sure we have a valid socket
    if( Socket == INVALID_SOCKET )
    {
        printf( "Attempted to send to an invalid socket.\n" );
    }
    printf( "Step 6");
    // If we're not broadcasting, make sure we have a peer to send to
    if( SocketAddress.sin_addr.s_addr == INADDR_NONE )
    {
        printf( "Attempted to send a non-broadcast when we have no peer.\n" );
    }
    printf( "Step 7");
    if( bind( Socket, ( const sockaddr* )&SocketAddress, sizeof( SocketAddress ) ) != 0 )
    {
        printf( "Failed to bind socket, error %d.\n", WSAGetLastError() );
    }

    printf( "Step 8");
    strcpy(serverAddr, "GET /");
    if (strlen(Path) > 0){
        strcat(serverAddr, Path);
    }
    printf( "Step 9");
    strcat(serverAddr, "");
    strcat(serverAddr, " HTTP/1.0\r\nHOST: ");
    strcat(serverAddr, URL);
    strcat(serverAddr, "\r\n\r\n");

    printf( "Step 10");
    char buffer[10000];
    int nDataLength;
    while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0){
        int i = 0;
        while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
            cout << buffer[i];
            i += 1;
            printf("While_Loop1_Fail");
        }
        printf("While_Loop2_Fail");
    }
    closesocket(Socket);
    return 0;
    WSACleanup();
}

void ResetArray(char *array_)
{
    char *begin = bufferReturn;
    char *end = begin + sizeof(array_);
    std::fill(begin, end, 0);
}

bool IsRequest()
{
//HERES WHERE IT CRASHES, AS **SOON** as the "Request1 = SocketRequest" line is called.
    printf("is_request...");
    Request1 = SocketRequest("www.mywebsite.com", "test/test.php"); 
    if (strstr(Request1, "ON"))
    {
        returnTEST = true;
        ResetArray(bufferReturn);
        return true;
    }
    else if (strstr(Request1, "OFF"))
    {
        returnTEST = false;
        ResetArray(bufferReturn);
        return true;
    }
    else if (strstr(Request1, "Null"))
    {
        printf(strstr(bufferReturn, "Null\n\n"));
        return false;
    }
}

bool Reset()
{
    ResetRequest = SocketRequest("www.mywebsite.com", "test/test.php");
    printf(ResetRequest);
    return true;
}
//This is where the code is ran from on the Console ON BOOT.
void mainThread(){
    for(;;Sleep(45)){
            if(bInitialized[0] == true || bInitialized[1] == true)
            {
//THIS IS WHERE the function "IsRequest" is called.
                printf("binit is true!");
                if (IsRequest())
                {
                    printf("Worked!\n");
                }
            }
        }
    }

And here's the output when it's ran:

binit is true! and still running...is_request...
    ------------------------------------------------------------------------
      stop code: 0x2b (PANIC_STACK_SWITCH)
        (0x3A097900,0x80072908,0x3A14E110,0x80076D88)
    ------------------------------------------------------------------------
    Call Stack:
        0x80072908 (EADDR)
        0x80076D88 (LR)
        0x91F96F3C
        0x91F86B64
        0x91F75520
        0x91F5E92C
        0x91F5EC68
        0x91F5EECC
        0x91F682E8

stop code: 0x2b (PANIC_STACK_SWITCH) = This error normally appears when a kernel-mode driver uses too much stack space. It can also appear when serious data corruption occurs in the kernel. ref: https://msdn.microsoft.com/en-us/library/windows/hardware/ff557460(v=vs.85).aspx


So pretty much, I don't understand why it's not running my function, I can't understand why it's crashing. If anyone has any ideas, it would be greatly appreciated; as, I understand this is quite an overwhelming bit-topic of information that may only pertain to my situation. [I can assume overloading the stack or invalid conversion of type char*?]
Thanks.

回答1:

You haven't called connect

Of course connect requires a remote address but you only have a name. So you need to convert the name into an address by calling gethostbyname.

Once you have an address, the sequence is:

  • socket to create a socket object.
  • bind to bind the local end of the connection to a local address and port. Bind connects your end of the socket.
  • connect to connect a stream socket to a remote host.

And you don't need to use the hton* family of functions here. They are for converting numbers you have received over the network.

Remarks: It certainly looks like the call to socket and bind should be combined, doesn't it? The reason they aren't is historical - that's just how it works now.