Problems with stringstream

Hi everybody.

I am testing HTTP headers using sockets. I have created a class to control them and I believe that this part is OK, but I have an strange behavior when I construct the request using stringstream. Using string seems to be correct.

The class to control sockets is the following:

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);
}


Using this 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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <sstream>
#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
		stringstream request;
		request << "HEAD / HTTP/1.1\r\n";
		request << "Host: www.ubuntu.com\r\n";
		request << "User-agent: My User Agent for Test 1, ";
		request << "My User Agent for Test 2, ";
		request << "My User Agent for Test 3, ";
		request << "My User Agent for Test 4, ";
		request << "My User Agent for Test 5, ";
		request << "My User Agent for Test 6, ";
		request << "My User Agent for Test 7, ";
		request << "My User Agent for Test 8, ";
		request << "My User Agent for Test 9, ";
		request << "My User Agent for Test 10, ";
		request << "My User Agent for Test 11, ";
		request << "My User Agent for Test 12, ";
		request << "My User Agent for Test 13, ";
		request << "My User Agent for Test 14, ";
		request << "My User Agent for Test 15, ";
		request << "My User Agent for Test 16, ";
		request << "My User Agent for Test 17";
		request << "\r\n";

		request << "\r\n";
	
		// Realizamos la peticion HTTP
		tcpSocket->Write(request.str().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);
	}
}


I have the following output:


HTTP REQUEST
------------
Conectando con www.ubuntu.com
Conectando con 91.189.90.59

HTTP/1.1 200 OK
Date: Sat, 07 Jun 2014 10:14:35 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Length: 17559
Content-Type: text/html; charset=utf-8
Age: 84
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

, My User Agent for Test 13, My User Agent for Test 14, My User Agent for Test 15, My User Agent for Test 16, My User Agent for Test 17



However, when I using this 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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <sstream>
#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 for Test 1, ");
		request.append("My User Agent for Test 2, ");
		request.append("My User Agent for Test 3, ");
		request.append("My User Agent for Test 4, ");
		request.append("My User Agent for Test 5, ");
		request.append("My User Agent for Test 6, ");
		request.append("My User Agent for Test 7, ");
		request.append("My User Agent for Test 8, ");
		request.append("My User Agent for Test 9, ");
		request.append("My User Agent for Test 10, ");
		request.append("My User Agent for Test 11, ");
		request.append("My User Agent for Test 12, ");
		request.append("My User Agent for Test 13, ");
		request.append("My User Agent for Test 14, ");
		request.append("My User Agent for Test 15, ");
		request.append("My User Agent for Test 16, ");
		request.append("My User Agent for Test 17");
		request.append("\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);
	}
}


I get the correct output:


HTTP REQUEST
------------
Conectando con www.ubuntu.com
Conectando con 91.189.89.110

HTTP/1.1 200 OK
Date: Sat, 07 Jun 2014 10:18:51 GMT
Server: Apache/2.2.22 (Ubuntu)
Cache-Control: public, max-age=300
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
Age: 1
Content-Length: 17559
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)



So, i don't understand because in the first case the response of the server is overlapped with the request. I think that it could be a problem with some buffer but i don't find the solution.

I want to discover what are happening because I want to use stringstream.

I am waiting a response as soon as possible.
Thanks a lot for your time.
1) Use ostringstrem instead of stringstream : you do not read anything for it, so you do not need that functionality.

2) Do not call c_str() on temporary string returned by str():
The copy of the underlying string returned by str is a temporary object that will be destructed at the end of the expression, so directly calling c_str() on the result of str() results in a dangling pointer.

Create a named variable to put string to:
1
2
3
4
{
    std::string temp = request.str();
    tcpSocket->Write(temp.c_str());
}
Last edited on
Topic archived. No new replies allowed.