Косяки с сокетами и непонятки с пониманием 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; } ?>
Чета я нехрена не понял про пхп! Это твой скрипт? Если да, то это полная чушь ))) 1)Вопользуйся навископом и посмотри как долен выглядить запрос... 2)ЧЕ ЭТА ЗА Х...
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
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(); } Это вырубка из моей программы. Не помню про что там, но работало =)
И еще вот один вариант . 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(); } Так по практичнее будет