Я пытаюсь сделать HTTP-запрос к серверу bittorrent-трекера, чтобы получить список пиров.
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> // for gethostbyname()
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
using namespace std;
struct in_addr *atoaddr( const char* address)
{
static struct hostent *host;
static struct in_addr saddr;
// First try nnn.nnn.nnn.nnn form
saddr.s_addr = inet_addr(address);
if (saddr.s_addr != -1)
return &saddr;
host = gethostbyname(address);
if( host )
return (struct in_addr *) *host->h_addr_list;
return 0;
}
int main(){
int numbytes=0;
int m_Port=80;
string m_Host="torrent.ubuntu.com";
int m_Sock;
struct hostent *host;
static struct in_addr saddr;
string buffer;
char* buf;
//HTTP request string
buffer.append("GET http://torrent.ubuntu.com:6969/announce HTTP/1.1\r\n");
buffer.append("Host: torrent.ubuntu.com\r\n");
buffer.append("Accept-Encoding: identity\r\n");
buffer.append("info_hash: %36%be%21%35%ab%cc%f4%03%2f%bb%28%bb%1b%0d%4f%da%f7%49%f8%58\r\n");
buffer.append("peer_id: ABCDEFGHIJKLMNOPQRST\r\n");
buffer.append("port: 6881\r\n");
buffer.append("compact: 1\r\n");
buffer.append("uploaded: 0\r\n");
buffer.append("downloaded: 0\r\n");
buffer.append("left: 987758592\r\n");
buffer.append("event: started\r\n");
buffer.append("\r\n");
in_addr* addr = atoaddr( m_Host.c_str() );
if( !addr )
{
cout<<"Error address\n";
return 1;
}
sockaddr_in address;
memset( (char*)&address, 0, sizeof(address) );
address.sin_family = AF_INET;
address.sin_port = htons( m_Port );
address.sin_addr.s_addr = addr->s_addr;
m_Sock = socket( AF_INET, SOCK_STREAM, 0 );
if(m_Sock<0){
cout<<"Socket error\n";
return 1;
}
if( ::connect( m_Sock, (sockaddr const*)&address, sizeof(address) ) < 0 )
{
cout<<"connect error";
return 1;
}
buf = (char*)buffer.c_str();
numbytes = buffer.length();
while( numbytes > 0 )
{
int n = ::send( m_Sock, buf, buffer.size(), 0 );
std::cout<<"\n\n--HTTP request:\n"<<buf<<std::endl;
if( n<0 )
{
cout<<"number of bytes sent <0\n";
return 1;
}
numbytes -= n;
buf += n;
}
cout<<"\ngetting response: \n";
unsigned char recvBuf[ 2048 ];
int a;
do{
a = recv( m_Sock, (char*)recvBuf, sizeof(recvBuf), 0 );
fwrite(recvBuf, 1, a, stdout);
}while(a!=0);
if(m_Sock>0)
close(m_Sock);
return 0;
}
Я всегда получаю ответ как:
HTTP/1.1 404 Not Found
Date: Sun, 16 Mar 2014 13:40:10 GMT
Server: Apache/2.2.22 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 294
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /announce was not found on this server.</p>
<hr>
<address>Apache/2.2.22 (Ubuntu) Server at bttracker.debian.org Port 6969</address>
</body></html>
Я попытался с расширением POSTMAN из Google Chrome сделать тот же запрос, и я получил ответ вроде:
d8:completei12e10:incompletei1e8:intervali1800e5:peers18:[�_�����4&N=;8��e
это то, что я ожидаю увидеть при выполнении запроса из моего C-кода. Что я делаю неправильно?
Я считаю, что ваш код не работает, потому что вы допустили небольшую ошибку: вместо того, чтобы подключить ваш сокет к порту 80, вы должны подключиться к порту 6969, а затем отправить GET /announce
запрос, вместо отправки полного URL-адреса в GET
метод.
Я использовал Wireshark (спасибо совету старого друга) для получения запроса, отправленного POSTMAN.
Вот код, который работал для меня:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> // for gethostbyname()
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
using namespace std;
// Try to work out address from string
// returns 0 if bad
struct in_addr *atoaddr( const char* address)
{
static struct hostent *host;
static struct in_addr saddr;
// First try nnn.nnn.nnn.nnn form
saddr.s_addr = inet_addr(address);
if (saddr.s_addr != -1)
return &saddr;
host = gethostbyname(address);
if( host )
return (struct in_addr *) *host->h_addr_list;
return 0;
}
int main(){
int numbytes=0;
int m_Port=6969;
string m_Host="torrent.ubuntu.com";
int m_Sock;
struct hostent *host;
static struct in_addr saddr;
string buffer;
char* buf;
// HTTP request string
// buffer.append("GET /announce HTTP/1.1\r\n");
// buffer.append("Host: torrent.ubuntu.com:6969\r\n");
// buffer.append("Accept-Encoding: identity\r\n");
// buffer.append("info_hash: %36%be%21%35%ab%cc%f4%03%2f%bb%28%bb%1b%0d%4f%da%f7%49%f8%58\r\n");
// buffer.append("peer_id: ABCDEFGHIJKLMNOPQRST\r\n");
// buffer.append("port: 6881\r\n");
// buffer.append("uploaded: 0\r\n");
// buffer.append("downloaded: 0\r\n");
// buffer.append("left: 987758592\r\n");
// buffer.append("compact: 1\r\n");
// buffer.append("event: started\r\n");
buffer.append("GET /announce?info_hash=%36%be%21%35%ab%cc%f4%03%2f%bb%28%bb%1b%0d%4f%da%f7%49%f8%58&""peer_id=ABCDEFGHIJKLMNOPQRST&""port=6881&""compact=1&""uploaded=0&""downloaded=0&""left=987758592&""event=started HTTP/1.1\r\n");
buffer.append("\r\n");
in_addr* addr = atoaddr( m_Host.c_str() );
if( !addr )
{
cout<<"Error address\n";
return 1;
}
sockaddr_in address;
memset( (char*)&address, 0, sizeof(address) );
address.sin_family = AF_INET;
address.sin_port = htons( m_Port );
address.sin_addr.s_addr = addr->s_addr;
m_Sock = socket( AF_INET, SOCK_STREAM, 0 );
if(m_Sock<0){
cout<<"Socket error\n";
return 1;
}
if( ::connect( m_Sock, (sockaddr const*)&address, sizeof(address) ) < 0 )
{
cout<<"connect error";
return 1;
}
buf = (char*)buffer.c_str();
numbytes = buffer.length();
while( numbytes > 0 )
{
int n = ::send( m_Sock, buf, buffer.size(), 0 );
std::cout<<"\n\n--HTTP request:\n"<<buf<<std::endl;
if( n<0 )
{
cout<<"number of bytes sent <0\n";
return 1;
}
numbytes -= n;
buf += n;
}
cout<<"\ngetting response: \n";
unsigned char recvBuf[ 2048 ];
int a;
do{
a = recv( m_Sock, (char*)recvBuf, sizeof(recvBuf), 0 );
fwrite(recvBuf, 1, a, stdout);
}while(a!=0);
cout<<"\n";
if(m_Sock>0)
close(m_Sock);
return 0;
}