PDA

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


je0n
28.06.2006, 00:53
Косяки с сокетами и непонятки с пониманием http-запросов
Я пытаюсь выучить winsock. Почти получается, но появилась проблема. У меня стоит апач и я подключаюсь программой которую написал на с++ к нему, т.е. к 127.0.0.1 на 80 порт. Затем делаю GET запрос на получение главной страницы, но в ответ не получаю вообще ничего. Я сначала думал, что проблема в моем запросе, но потом поставил тот же запрос в программу на php (идентичную) и апач вернул сообщение bad request. Мои косяки в запросе подтвердились, но ведь и программа на c++ тогда должна была вернуть это сообщение с “bad request”. А она вообще ничего не вернула. Вот у меня два вопроса.
1) как должен выглядеть минимальный GET запрос? Мой запрос вы увидите дальше по тексту в исходниках программ.
2) почему программа на с++ не получает ответа от сервера.?


Вот исходники тех программ:
C++:

#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:

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

bul.666
28.06.2006, 01:36
Чета я нехрена не понял про пхп! Это твой скрипт? Если да, то это полная чушь )))

1)Вопользуйся навископом и посмотри как долен выглядить запрос...
2)ЧЕ ЭТА ЗА Х... echo $tosend."<br>";

grinay
28.06.2006, 01:40
#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

fucker"ok
28.06.2006, 01:59
#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();
}

Это вырубка из моей программы. Не помню про что там, но работало =)

grinay
28.06.2006, 02:56
И еще вот один вариант .

#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();
}

Так по практичнее будет