Косяки с сокетами и непонятки с пониманием http-запросов

Discussion in 'PHP' started by je0n, 28 Jun 2006.

  1. je0n

    je0n Elder - Старейшина

    Joined:
    14 May 2006
    Messages:
    345
    Likes Received:
    96
    Reputations:
    41
    Косяки с сокетами и непонятки с пониманием http-запросов
    Я пытаюсь выучить winsock. Почти получается, но появилась проблема. У меня стоит апач и я подключаюсь программой которую написал на с++ к нему, т.е. к 127.0.0.1 на 80 порт. Затем делаю GET запрос на получение главной страницы, но в ответ не получаю вообще ничего. Я сначала думал, что проблема в моем запросе, но потом поставил тот же запрос в программу на php (идентичную) и апач вернул сообщение bad request. Мои косяки в запросе подтвердились, но ведь и программа на c++ тогда должна была вернуть это сообщение с “bad request”. А она вообще ничего не вернула. Вот у меня два вопроса.
    1) как должен выглядеть минимальный GET запрос? Мой запрос вы увидите дальше по тексту в исходниках программ.
    2) почему программа на с++ не получает ответа от сервера.?


    Вот исходники тех программ:
    C++:
    Code:
    #include <stdio.h>
    #include <winsock.h>
    #include <windows.h>
    
    int main()
    {
    	WSADATA wsadata;
    	int s,char_len;
    	LPSTR str;
    	struct sockaddr_in addr_c,addr_s;
    
    	WSAStartup(MAKEWORD(2,0),&wsadata);
    	s=socket(AF_INET,SOCK_STREAM,0);
    	memset((char *)&addr_c,0,sizeof(addr_c));
    	addr_c.sin_family=AF_INET;
    	addr_c.sin_port=80;
    	addr_c.sin_addr.s_addr=INADDR_ANY;
    	bind(s,(struct sockaddr *)&addr_c,sizeof(addr_c));
    
    	memset((char *)&addr_s,0,sizeof(addr_s));
    	addr_s.sin_family=AF_INET;
    	addr_s.sin_port=80;
    	addr_s.sin_addr.s_addr=inet_addr("127.0.0.1");
    
    	if(connect(s,(struct sockaddr *)&addr_s,sizeof(addr_s))==-1)puts("connect error");
    	str=(LPSTR)GlobalAlloc(GHND,0);
    	str="GET index.html HTTP/1.1\r\n\r\n";
    	send(s,str,100,0);
    	char_len=recv(s,str,1000,0);
    	puts(str);
    	puts("end...");
    	return 0;
    }
    

    php:
    Code:
    <?php
    $tosend="GET index.html HTTP/1.1\r\n\r\n ";
    echo $tosend."<br>";
    $s=fsockopen("127.0.0.1",80);
    if($s)
    {
      fwrite($s,$tosend);
      $tosend=fread($s,1000);
      echo $tosend;
    }
    ?>
    
     
  2. bul.666

    bul.666 булка

    Joined:
    6 Jun 2006
    Messages:
    719
    Likes Received:
    425
    Reputations:
    140
    Чета я нехрена не понял про пхп! Это твой скрипт? Если да, то это полная чушь )))

    1)Вопользуйся навископом и посмотри как долен выглядить запрос...
    2)ЧЕ ЭТА ЗА Х...
     
    #2 bul.666, 28 Jun 2006
    Last edited: 28 Jun 2006
  3. grinay

    grinay IQ- 137%

    Joined:
    15 Jun 2004
    Messages:
    409
    Likes Received:
    174
    Reputations:
    305
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <WinSock2.h>
    #pragma comment(lib, "ws2_32")
    #define CHECK_URL(x,y) if (x) {fprintf(stderr, ToConsole(y)); return NULL;}
    
    struct sockaddr_in sa;
    char buf[1024];
    char conBuf[1024];
    char* ToConsole(char* str)
    {
    CharToOem(str, conBuf);
    return conBuf;
    }
    char* parseURL(char* _url)
    {
    char *ptr = strchr(_url, ':');
    CHECK_URL(ptr == NULL, "Имя протокола отсутствует.\n");
    *ptr = '\0';
    CHECK_URL(stricmp(_url, "http") != 0, "Недопустимое имя протокола.\n");
    CHECK_URL(strncmp(++ptr, "//", 2) != 0, "Неправильный формат URL.\n");
    
    ptr+=2;
    char* eptr = strchr(ptr, '/');
    CHECK_URL(eptr == NULL, "Нет имени страницы");
    strcat(buf, eptr+1);
    
    *eptr = '\0';
    eptr = strchr(ptr, ':');
    if (eptr != NULL)
    {
    char* leptr;
    short port = (short)strtol(eptr+1,&leptr, 10);
    if (eptr == leptr) port = 80;
    *eptr = '\0';
    sa.sin_port = htons(port);
    }
    else
    sa.sin_port = htons(80);
    
    struct hostent *he = gethostbyname(ptr);
    if (he == NULL)
    {
    he = gethostbyaddr(ptr, strlen(ptr), AF_INET);
    CHECK_URL(he == NULL, "Недопустимое имя сервера");
    }
    memcpy(&sa.sin_addr.S_un.S_addr, he->h_addr, sizeof(sa.sin_addr.S_un.S_addr));
    return buf;
    }
    
    int main(int argc, char **argv)
    {
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    
    wVersionRequested = MAKEWORD( 1, 1 );
    
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 )
    {
    fprintf(stderr, ToConsole("Невозможно инициализировать Windows Sockets.\n"));
    return 0;
    }
    
    if ( LOBYTE( wsaData.wVersion ) != 1 ||HIBYTE( wsaData.wVersion ) != 1 )
    {
    fprintf(stderr, ToConsole("Максимально доступная версия Windows Sockets : %d.%d - недопустима."),
    (int)(LOBYTE( wsaData.wVersion )),(int)(HIBYTE( wsaData.wVersion )));
    WSACleanup( );
    return 0;
    }
    
    
    struct protoent *pe = getprotobyname("tcp");
    SOCKET sock = socket(AF_INET, SOCK_STREAM, pe->p_proto);
    
    strcpy(buf, "GET /");
    if (argc >= 2)
    {
    if (parseURL(argv[1]) == NULL)
    { closesocket(sock); WSACleanup(); return 0; }
    }
    else
    parseURL("http://localhost:80/index.php");
    strcat(buf, " HTTP/1.0\n\n");
    
    sa.sin_family = AF_INET;
    memset(&sa.sin_zero, 0, sizeof(sa.sin_zero));
    if (connect( sock, (struct sockaddr*)(&sa), sizeof(sa)) != 0)
    {
    fprintf(stderr, ToConsole("Ошибка при подключении №%d\n"), WSAGetLastError());
    closesocket(sock); WSACleanup(); return 0;
    }
    send(sock, buf, strlen(buf), 0);
    char recvbuf[1024];
    int received = 0;
    while((received = recv(sock,recvbuf, sizeof(recvbuf)-1,0)) > 0)
    {
    recvbuf[received] = '\0';
    fprintf(stdout, recvbuf);
    }
    closesocket(sock);
    WSACleanup();
    }
    
    Да кстати не сказал ..
    parseurl.exe http://exemple.com:80/test.html

    или парситься значение по умолчанию тоесть localhost
     
    #3 grinay, 28 Jun 2006
    Last edited: 28 Jun 2006
  4. fucker"ok

    fucker"ok Elder - Старейшина

    Joined:
    21 Nov 2004
    Messages:
    578
    Likes Received:
    274
    Reputations:
    91
    Code:
    #include <winsock.h>
    #include <string>
    #include <iostream>
    int main()
    {
    WSADATA lpWSAData;
    if (WSAStartup(MAKEWORD(1,1),&lpWSAData)!=0) return 1;
    int sock;
    struct sockaddr_in sin;
    struct hostent* hp;
    memset(&sin, 0, sizeof(sin));
    hp = gethostbyname("google.com");
    memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
    sin.sin_family = hp->h_addrtype;
    sin.sin_port = htons(80);
    
    string query="GET / HTTP/1.0\r\n";
    sock = socket(PF_INET,SOCK_STREAM,0);
    connect(sock, (struct sockaddr *) &sin, sizeof(sin));
    send(sock, query.c_str(), query.size(), 0);
    char c;
    string result;
    while (recv(sock, &c ,1,0)) result+=c;
    cout << result;
    closesocket(sock);
    
    WSACleanup();
    }
    
    Это вырубка из моей программы. Не помню про что там, но работало =)
     
    #4 fucker"ok, 28 Jun 2006
    Last edited: 28 Jun 2006
  5. grinay

    grinay IQ- 137%

    Joined:
    15 Jun 2004
    Messages:
    409
    Likes Received:
    174
    Reputations:
    305
    И еще вот один вариант .
    Code:
    #include <stdio.h>
    #include <winsock.h>
    #pragma comment(lib, "ws2_32")
    char url[]="sec.antichat.org";
    char document[]="domain3.txt";
    int port=80;
    
    int main()
    {
    char buf[1024];
    WSADATA wsaData;
    WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
    SOCKET sock = socket(AF_INET, SOCK_STREAM,0);
    struct sockaddr_in sa;
    sa.sin_port = htons(port);
    struct hostent *he = gethostbyname(url);
    memcpy(&sa.sin_addr, he->h_addr, sizeof(sa.sin_addr));
    sa.sin_family = AF_INET;
    memset(&sa.sin_zero, 0, sizeof(sa.sin_zero));
    connect( sock, (struct sockaddr*)(&sa), sizeof(sa));
    
    sprintf(buf,
    "GET /%s HTTP/1.0\r\n"\
    "Host: %s\r\n"\
    "Connection: Close\r\n\r\n",
    document,url);
    
    send(sock, buf, strlen(buf), 0);
    char recvbuf[1024];
    int received = 0;
    while((received = recv(sock,recvbuf, sizeof(recvbuf)-1,0)) > 0)
    {
    recvbuf[received] = '\0';
    fprintf(stdout, recvbuf);
    }
    closesocket(sock);
    WSACleanup();
    }
    
    Так по практичнее будет
     
    #5 grinay, 28 Jun 2006
    Last edited: 28 Jun 2006