2

I'm new to Qt, so if this is a completely stupid question...

I'm trying to use QTcpSocket.

If I do:

...
QTcpSocket * socket
socket = new QTcpSocket(this);
socket.write(1);
...

It complains about write() not working with integers (not a const char *).

If I do:

...
QTcpSocket * socket
socket = new QTcpSocket(this);
socket.write("1");
...

the other side sees it as the integer 49 (ASCII for 1).

On a similar but different issue, is it possible to send structs or unions over QTcpSocket?

==================================================

EDIT:

The server already accepts integers, and is expecting an integer - I have no control over that.

Sagar
  • 9,456
  • 6
  • 54
  • 96
  • 1
    It's not really enough to say that the server is expecting an integer. The server is expecting a series of bytes representing an integer. How that integer is **encoded** (what goes into the bytes), the **number of bytes** and the **order** of the bytes are what you need to know and send, along with any other protocol specific bytes, if any. – Arnold Spence Aug 16 '11 at 18:12

4 Answers4

4

The problem you have is not really related to Qt, the same issue would arise with any other Socket or Streaming interface.

The provider of the Server needs to give you the protocol description. This description usually contains the ports used (TCP, UDP, numbers), other TCP parameters and the coding of the transmitted data. Sometimes, this protocol (or its implementation) is called a (protocol-) stack.

The coding not only contains the byte ordering, but also a description of how complex structures are transmitted. The latter information is often coded in something that is called "ASN.1" - Abstract Syntax Notation.

In case your server is really simple and just accepts Integers one after the other without any meta-information and is on the same platform, than you could do something like this:

foreach (int i in my set of integers)
{
   ioDevice->write((const char*) &i, sizeof(i));
}

You take the address of your integer as a data buffer start and transmit as many bytes as your integer has. But note well, this will fail if you transmit data from an Intel architecture to a 16-bit architecture or a motorola PPC.

Jens
  • 6,173
  • 2
  • 24
  • 43
  • I already know the TCP address, port numbers, etc. The problem is related to Qt, because if I use the socket implementation provided by sys/socket.h in unix (for example), I can send structures, integers, whatever else I like. I just want to know if I can do that here - ie, send integers. Nothing to do with the byte ordering, or the protocol stack... – Sagar Aug 16 '11 at 18:23
  • I think there is some misunderstanding on my or your side left: which function from sys/socket.h exactly do you mean? – Jens Aug 17 '11 at 10:05
  • If you use the standard socket provided by gcc, you can write directly to the sockfd, using write(). [See here][http://www.linuxhowtos.org/C_C++/socket.htm]. Just found out I can do the same with the qtcpsocket write() – Sagar Aug 17 '11 at 13:49
  • Yep, that's what helped me! Thanks! – Sagar Aug 17 '11 at 19:10
4

I suggest using QDataStream with sockets. This will protect you from little endian/big endian conversion problem.

So something as below :

qint32 myData = 1;
QDataStream os( &mySocket );
os << myData;
Christophe Weis
  • 2,518
  • 4
  • 28
  • 32
O.C.
  • 6,711
  • 1
  • 25
  • 26
1

When you write in a string representation, you also have to interpret the string on the other side. There is, for example, QString::toInt().

When you want to write the integer as integer, you will have more throughput, as it takes less bytes to transmit. However you should read about the topic of network byte order.

In principal it is possible to copy structs, etc. into a buffer and also over the network. However things get complicated again when you transmit data between different architectures or even only different builds of your software. So you shouldn't send the raw data, but use serialization! See this question: Serialization with Qt

It provides answers on how to generate streams out of objects and objects out of streams. These streams is what you then use to transmit over the network. Then you don't have to deal with the integers themselves anymore!

Community
  • 1
  • 1
ypnos
  • 50,202
  • 14
  • 95
  • 141
  • Thanks! I'll try sending the data using data streams, although I'm not sure if the server will see that correctly. Will post back. – Sagar Aug 16 '11 at 16:20
  • Nope, it looks like I need to send either the integer itself, followed by the other stuff, or the structure which contains the integer and the other stuff... – Sagar Aug 16 '11 at 17:38
  • Are you sure QDataStream does not work? See this example: http://doc.qt.nokia.com/latest/network-fortuneclient.html – ypnos Aug 17 '11 at 10:30
  • That's the example I was trying to follow. May be I did it wrong, but the server did not see it correctly. I know the server is not programmed well (it is quite old) but unfortunately it is out of my hands.. – Sagar Aug 17 '11 at 13:46
  • I see. This was not clear in the original version of the question. Then the server expects the number not in network transparent byte order but in machine byte order. That sucks. To be on the safe side, you should care for byte order by explicitely converting to that machine's byte order.. – ypnos Aug 17 '11 at 14:08
  • Yeah, sorry about that. I should have specified that. Thank you for your help though, really! – Sagar Aug 17 '11 at 14:11
0

Different overloads, you are looking for:

qint64 QIODevice::write ( const char * data, qint64 maxSize );

and

qint64 QIODevice::write ( const QByteArray & byteArray );
Christophe Weis
  • 2,518
  • 4
  • 28
  • 32
Nikolai Fetissov
  • 82,306
  • 11
  • 110
  • 171
  • I know the two overloads. I was just wondering if there was some way to send integers too. Thanks though! – Sagar Aug 16 '11 at 16:19