Problems with for loop and strings
Jun 23, 2014 at 10:34am UTC
Hi everybody. I am testing HTTP Headers and I have an strange problem. When I get the response of the server, it is the correct one the first time. If I use a for loop to send more than one request and get more than one response, this response seems to be overlapped with the previous ones.
To a better explanation of the problem I attach the code I am using and the output generated:
TCPSocket.h
-----------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#ifndef _TCPSOCKET_H_
#define _TCPSOCKET_H_
class TCPSocket
{
private :
int localSocket;
public :
TCPSocket();
~TCPSocket();
void Connect(const char *host, int port);
void Write(const char *data);
char *Read();
};
#endif
TCPSocket.cpp
-------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "TCPSocket.h"
using namespace std;
TCPSocket::TCPSocket()
{
localSocket = socket(AF_INET, SOCK_STREAM, 0);
if (localSocket == -1) throw "No se puede crear el socket" ;
}
TCPSocket::~TCPSocket()
{
int result = close(localSocket);
if (result == -1) throw "No se puede cerrar el socket" ;
}
void TCPSocket::Connect(const char *host, int port)
{
struct hostent *server = gethostbyname(host);
if (server == NULL) throw "No se encuentra el host" ;
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(port);
serverAddress.sin_addr = *(struct in_addr *)(server->h_addr_list[0]);
bzero(&(serverAddress.sin_zero), 8);
cout << "Conectando con " << host << endl;
cout << "Conectando con " << inet_ntoa(serverAddress.sin_addr) << endl;
int result = connect(localSocket, (struct sockaddr *) &serverAddress, sizeof (serverAddress));
if (result == -1) throw "No se puede conectar con el host" ;
}
void TCPSocket::Write(const char *data)
{
int dataLength = strlen(data);
int sent = send(localSocket, data, dataLength, 0);
if (sent == -1) throw "No se pueden enviar los datos al host" ;
if (sent != dataLength) throw "No se han podido enviar todos los datos al host" ;
}
char *TCPSocket::Read()
{
const int MAX_DATA_LENGHT = 16384;
char *data = new char [MAX_DATA_LENGHT];
int received = recv(localSocket, data, MAX_DATA_LENGHT, 0);
if (received == -1) throw "No se pueden recibir los datos del host" ;
return (data);
}
Main.cpp
--------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#include <iostream>
#include "TCPSocket.h"
using namespace std;
int main()
{
try
{
cout << "HTTP REQUEST" << endl;
cout << "------------" << endl;
// Establecemos la conexion con el servidor
TCPSocket *tcpSocket = new TCPSocket();
tcpSocket->Connect("www.ubuntu.com" , 80);
// Generamos la peticion HTTP
string request = "" ;
request.append("HEAD / HTTP/1.1\r\n" );
request.append("Host: www.ubuntu.com\r\n" );
request.append("User-agent: My User Agent\r\n" );
request.append("\r\n" );
for (int i = 0; i < 5; i++)
{
// Realizamos la peticion HTTP
tcpSocket->Write(request.c_str());
// Obtenemos la respuesta del servidor
char *data = tcpSocket->Read();
string response = string(data);
cout << endl << response << endl;
}
delete tcpSocket;
return (0);
}
catch (const char *e)
{
cout << "Excepcion: " << e << endl;
return (-1);
}
}
The output generated is the following:
HTTP REQUEST
------------
Conectando con www.ubuntu.com
Conectando con 91.189.90.58
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 10:26:31 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 26
Content-Length: 17555
X-Cache: HIT from avocado.canonical.com
X-Cache-Lookup: HIT from avocado.canonical.com:80
Via: 1.1 avocado.canonical.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 10:26:31 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 26
Content-Length: 17555
X-Cache: HIT from avocado.canonical.com
X-Cache-Lookup: HIT from avocado.canonical.com:80
Via: 1.1 avocado.canonical.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 10:26:31 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 26
Content-Length: 17555
X-Cache: HIT from avocado.canonical.com
X-Cache-Lookup: HIT from avocado.canonical.com:80
Via: 1.1 avocado.canonical.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 10:26:31 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 26
Content-Length: 17555
X-Cache: HIT from avocado.canonical.com
X-Cache-Lookup: HIT from avocado.canonical.com:80
Via: 1.1 avocado.canonical.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 10:26:31 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 26
Content-Length: 17555
X-Cache: HIT from avocado.canonical.com
X-Cache-Lookup: HIT from avocado.canonical.com:80
Via: 1.1 avocado.canonical.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
: 1.1 www.ubuntu.com
So, a bigger loop, a bigger the response of the server. However, I know the response of the server is always the same.
I don't understand what it is happening and I am very worried about it.
I hope someone have the answer.
Thanks in advance.
Jun 23, 2014 at 11:46am UTC
You're not telling the server that you intend to reuse the connection. You need to set the relevant header.
Jun 23, 2014 at 12:25pm UTC
Hi, but this not solve the problem. If I close de connection inside de for loop I obtain a similar result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include <iostream>
#include "TCPSocket.h"
using namespace std;
int main()
{
try
{
for (int i = 0; i < 5; i++)
{
cout << "HTTP REQUEST" << endl;
cout << "------------" << endl;
// Establecemos la conexion con el servidor
TCPSocket *tcpSocket = new TCPSocket();
tcpSocket->Connect("www.ubuntu.com" , 80);
// Generamos la peticion HTTP
string request = "" ;
request.append("HEAD / HTTP/1.1\r\n" );
request.append("Host: www.ubuntu.com\r\n" );
request.append("User-agent: My User Agent\r\n" );
request.append("\r\n" );
// Realizamos la peticion HTTP
tcpSocket->Write(request.c_str());
// Obtenemos la respuesta del servidor
char *data = tcpSocket->Read();
string response = string(data);
cout << endl << response << endl;
delete tcpSocket;
}
return (0);
}
catch (const char *e)
{
cout << "Excepcion: " << e << endl;
return (-1);
}
}
The output in this case is the following:
HTTP REQUEST
------------
Conectando con www.ubuntu.com
Conectando con 91.189.90.59
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 12:19:21 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 167
Content-Length: 17555
X-Cache: HIT from jujube.canonical.com
X-Cache-Lookup: HIT from jujube.canonical.com:80
Via: 1.1 jujube.canonical.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
HTTP REQUEST
------------
Conectando con www.ubuntu.com
Conectando con 91.189.90.58
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 12:21:31 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 37
Content-Length: 17555
X-Cache: HIT from avocado.canonical.com
X-Cache-Lookup: HIT from avocado.canonical.com:80
Via: 1.1 avocado.canonical.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
1.1 www.ubuntu.com
HTTP REQUEST
------------
Conectando con www.ubuntu.com
Conectando con 91.189.89.118
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 12:21:50 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 18
Content-Length: 17555
X-Cache: HIT from nuno.canonical.com
X-Cache-Lookup: HIT from nuno.canonical.com:80
Via: 1.1 nuno.canonical.com:80 (squid/2.7.STABLE7)
al.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
1.1 www.ubuntu.com
HTTP REQUEST
------------
Conectando con www.ubuntu.com
Conectando con 91.189.89.118
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 12:21:50 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 18
Content-Length: 17555
X-Cache: HIT from nuno.canonical.com
X-Cache-Lookup: HIT from nuno.canonical.com:80
Via: 1.1 nuno.canonical.com:80 (squid/2.7.STABLE7)
(squid/2.7.STABLE7)
al.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
1.1 www.ubuntu.com
HTTP REQUEST
------------
Conectando con www.ubuntu.com
Conectando con 91.189.90.59
HTTP/1.1 200 OK
Date: Mon, 23 Jun 2014 12:19:21 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 167
Content-Length: 17555
X-Cache: HIT from jujube.canonical.com
X-Cache-Lookup: HIT from jujube.canonical.com:80
Via: 1.1 jujube.canonical.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
2.7.STABLE7)
al.com:80 (squid/2.7.STABLE7)
Via: 1.1 www.ubuntu.com
1.1 www.ubuntu.com
So the problem remain and I don't understand where is the error.
Thanks.
Jun 23, 2014 at 2:37pm UTC
You have a problem with your code.
1 2 3 4 5 6 7 8 9 10 11
char *TCPSocket::Read()
{
const int MAX_DATA_LENGHT = 16384;
char *data = new char [MAX_DATA_LENGHT];
int received = recv(localSocket, data, MAX_DATA_LENGHT, 0);
if (received == -1) throw "No se pueden recibir los datos del host" ;
// data[received] = 0; // you forgot this line
return (data);
}
Then later on:
1 2
char *data = tcpSocket->Read();
string response = string(data);
The buffer isn't null terminated, so the final string
will have uninitialsed data.
Also, you don't free the buffer.
Last edited on Jun 23, 2014 at 3:00pm UTC
Topic archived. No new replies allowed.