Problems with for loop and strings

Jun 23, 2014 at 10:34am
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
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
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
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
Topic archived. No new replies allowed.