Запросы POST и GET посредством socket winapi

При работе с запросом POST параметры запроса добавляются в конец запроса после завершающей последовательности \r\n\r\n. При использовании GET запроса параметры указываются в теле запроса, как обычно это делается в адресной строке, используя символ ?. То есть вся разница в том как формируется строка запроса перед тем как она посылается на сервер.

Пример строки которая описывает тело запроса POST. Как видим, это массив символов, в котором элементы строки запроса разделяются \r\n, а завершается тело запроса символами \r\n\r\n, после чего добавляются параметры, передаваемые в запросе, в нашем случае это "username=USER&passwd=PASS".

char buff2[9000]= {
"POST /member.php HTTP/1.0\r\n"
"Host: www.website.com\r\n"
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.13) Gecko/20080311 AdCentriaIM/1.7
Firefox/2.0.0.13\r\n"
"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"
"Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
"Accept-Encoding: gzip,deflate\r\n"
"Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7\r\n"
"Keep-Alive: 300\r\n"
"Connection: keep-alive\r\n"
"Referer: http://www.haddan.ru/\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: 33\r\n\r\n"
"username=USER&passwd=PASS"



Аналогично этот же заголовок запроса будет выглядеть в случае GET запроса.

char buff2[9000]= {
"GET /member.php?username=USER&passwd=PASS HTTP/1.0\r\n"
"Host: www.website.com\r\n"
"User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.13) Gecko/20080311 AdCentriaIM/1.7
Firefox/2.0.0.13\r\n"
"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n"
"Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3\r\n"
"Accept-Encoding: gzip,deflate\r\n"
"Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7\r\n"
"Keep-Alive: 300\r\n"
"Connection: keep-alive\r\n"
"Referer: http://www.haddan.ru/\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: 33\r\n\r\n"



Ниже представлен код С++ который производит отправку POST запроса.

CString lpAddr = "dns.com.ua";
SOCKET m_hSocket;
if((m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))== INVALID_SOCKET )
AfxMessageBox("Socket Error");
SOCKADDR_IN sockAddr;
ZeroMemory(&sockAddr, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons((u_short) 80);
sockAddr.sin_addr.s_addr = inet_addr(lpAddr);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(lpAddr);
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
WSASetLastError(WSAEINVAL);
}
}
if(connect(m_hSocket, (PSOCKADDR)&sockAddr, sizeof(sockAddr))!= INVALID_SOCKET )
{
AfxMessageBox("Connect OK!");
char szHeader[1024]= {
"POST /ajax/whois?domain=192.162.134.4 HTTP/1.1\r\n"
"x-requested-with: XMLHttpRequest\r\n"
"Accept-Language: ru\r\n"
"Referer: http://dns.com.ua/whois#192.162.134.4\r\n"
"Accept: text/html, */*; q=0.01\r\n"
"Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)\r\n"
"Host: dns.com.ua\r\n"
"Content-Length: 9\r\n"
"Connection: Keep-Alive\r\n"
"Cache-Control: no-cache\r\n"
"Cookie: hl=ru\r\n\r\n"
"type=POST"
};
//в конце POST запроса данные которые передаются в нашем случае это type=POST
send( m_hSocket, szHeader, (int)strlen(szHeader), 0);
char strBody[20480];
int nRead = recv( m_hSocket, strBody, 20480, 0 );


В результате этого POST запроса мы получим html страницу с информацией whois об IP адресе 192.162.134.4, которая будет находится в буфере strBody.



Теперь рассмотрим код С++ запроса GET.

CString lpAddr = "translate.google.com";
SOCKET m_hSocket;
if((m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))== INVALID_SOCKET )
AfxMessageBox("Socket Error");
SOCKADDR_IN sockAddr;
ZeroMemory(&sockAddr, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons((u_short) 80);
sockAddr.sin_addr.s_addr = inet_addr(lpAddr);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(lpAddr);
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
WSASetLastError(WSAEINVAL);
}
}
if(connect(m_hSocket, (PSOCKADDR)&sockAddr, sizeof(sockAddr))!= INVALID_SOCKET )
{
AfxMessageBox("Connect OK!");
char szHeader[1024]= {
"GET /translate_a/t?client=t&sl=en&tl=ru&hl=ru&sc=2&ie=Windows-1251&oe=Windows-1251&prev=btn&ssel=0&tsel=0&q=good HTTP/1.1\r\n"
"User-Agent: Opera/9.80 (Windows NT 5.1) Presto/2.12.388 Version/12.16\r\n"
"Host: translate.google.com.ua\r\n"
"Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1\r\n"
"Accept-Language: ru-RU,ru;q=0.9,en;q=0.8\r\n"
"Accept-Encoding: deflate\r\n"
"Referer: http://translate.google.com.ua/?hl=ru&tab=wT\r\n"
"Connection: Keep-Alive\r\n\r\n"
};
send( m_hSocket, szHeader, (int)strlen(szHeader), 0);
char szBuff[10240];
int nRead = recv( m_hSocket, szBuff, 10240, 0 );
szBuff[nRead] = '\0';
CStdioFile f;
f.Open("page.html", CFile::modeCreate|CFile::modeWrite|CFile::typeText);
f.Write( szBuff, strlen(szBuff) );
f.Close(); // закрываем файл

В данном коде мы послали запрос на сервер translate.google.com, в теле запроса указали через параметр q что будем переводить слово good т.е. это часть запроса q=good, в результате html страницу с переводом слова (для наглядности) мы сохранили в файл page.html. Позже переменную с ответом от сервера szBuff или сам файл page.html можно парсить для вывода на экран перевода данного слова. Причем в теле запроса вместе со словом которое необходимо перевести, так же через переменные указано что перевод должен осуществляться с английского языка на русский.