at the moment My socket conversation is text based. I end all my conversation end with a ; and some conversations are binary. now I've decided to make all my conversations binary. and I want to use QDataStream as the socket wrapper. so what measures should I take in place of ; usage.
e.g. i used to check for the ; at the end. when readyRead was emitted. now I think I'll put the buffer size at the begening of the buffer. but the problem is when I get some incomplete buffer. can I parse the size ?
Neel, I'd recommend you the following: QDataStream has convenient overloaded "operator>>" and "operator<<". What I usually do in such case is define the size of the data to be, for example, first 4 bytes of the stream. And on the other end I expect those 4 bytes to be read to determine the whole data size.
For example some pseudo code (C++ style but just gives and idea what you need rather than 100% polished and working code):
QByteArray myData = getData();
QDataStream ds(&socket);
ds << myData.size();
// Note: here your data will be encoded and be '\0' terminated
ds << myData.constData();
// so you might want to consider this call
// although since Qt doesn't guarantee exactly myData.size bytes to be written
// its your responsibility to check whether everything is written
ds.writeRawData(myData.constData(), myData.size());
Now, if you use QByteArray or any of the Qt types that can be sent through QDataStream, you can take advantage of what is already implemented in Qt and send your data as simple as:
QByteArray myData = getData();
QDataStream ds(&socket);
ds << myData;
In this case just check here http://doc.qt.nokia.com/4.7/datastreamformat.html of how Qt writes QByteArray to QDataStream. Even more: if you have QDataStream on the second end, all you need to do is just read your data as easy as you wrote it.
Hope that helps.
Related
I am using QXmlStreamWriter to create an xml file with many items. At one point because there are too many elements probably I experience a crash.
Is there a way to perform a flush on the stream?
How else can I perform the writing so I do not experience a crash?
Found out that QByteArray doesn't support more than 2GB. That's why i had a crash. I used QXmlStreamWriter together with a QByteArray.
If I provide the file directly it works fine.
previous code:
QByteArray buffer;
QXmlStreamWriter stream(&buffer);
current code:
QFile* destFile
QXmlStreamWriter stream(destFile);
How I can write data in serial port, with delay between send's messages?
This is my code:
void MainWindow::on_pushButton_Done_clicked()
{
if(sport->isOpen()){
sport->clear();
QString cmd = Phase+Mode;
//Write Stop
sport->write("stop!", 5);
//Write Mode
sport->write(cmd.toStdString().c_str(), cmd.toStdString().length());
//Write Speed
sport->write(Speed.toStdString().c_str(), Speed.toStdString().length());
//Write Direction
sport->write(Direction.toStdString().c_str(), Direction.toStdString().length());
//Run
sport->write("start!", 6);
}
}
My device receives an error message when I call this function.
Thank you.
2 options:
use waitForBytesWritten to ensure the bytes are written and then a short sleep
however this will block the thread and will block the gui
the other is using a QTimer to trigger another slot a few times and a field that will indicate what needs to be sent
Looks like you are trying to program some step motor controller or something similar.
Usually in such controllers you should wait for controller response to verify that command was processed properly.
It looks like that your design of code is very bad. Move everything related with this controller to separate class, which has set of slots, something like: starRotateLeftWithSpeed(double). Code will be cleaner and it will be easy to use thread if you decide to use methods like waitForBytesWritten proposed in another answer.
Definitely you should read controller manual more carefully.
I have a list of files and I'd like to serialize the file info for every file and send it through socket.
I saw it's possible to serialize like this for example:
QByteArray ba;
QDataStream ds(&ba);
ds << my_stringlist;
QByteArray ba;
QDataStream ds(&ba);
ds >> my_stringlist;
but I couldn't find support for QFileInfo. Is it possible to serialize this Qt data type?
Is there any way to get an easy full serialization of this type or I just need to break up the data into primitive units?
There is no standard way to do that. You can define your custom QDataStream operators as showed in this answer, or you can write your own functions to convert QFileInfo to QVariant and back, and use QVariant serialization. In all these ways you need to break up the data into primitive units, yes.
However I think serializing QFileInfo is pointless. You should use QFileInfo::absoluteFilePath() to get the file's path and serialize that path instead. A new QFileInfo object can be easily constructed from that path if your receiving code is running on the same machine.
If your code is running on the other machine, you couldn't use deserialized QFileInfo even if it would be possible. It's because QFileInfo may or may not store information about file. When you run e.g. QFileInfo::isFile, it may make a request to the underlying file system.
So I think it's better to request all required data from QFileInfo add send this data instead of sending QFileInfo. Or you can just send the absolute file path.
I am currently writing an app on the Blackberry to do a simple send and receive of some raw data to another TCP based device on my network. I am having the same problem in the Blackberry simulator w/ an MDS simulator running and using a physical phone talking to my company's MDS server. Note this problem does not happen when using wifi directly and not via MDS.
The problem is that the available() function on the InputStream returns zero unless I call read() first. If I call read first (knowing there is some data available .. thank you wireshark) the data comes back, and the subsequent call to available() indicates what data is left that I did not read. The problem is that I am not always going to be guaranteed that data will be there and so I could block. Is anyone aware of this, and is this a problem or something that is by design?
Is anyone aware of a way to test if the read() method(s) will block before calling them aside from available?
Here is basically what I am doing:
SocketConnection s = (SocketConnection)Connector.open("socket://1.2.3.4:port;deviceside=false", Connector.READ_WRITE);
OutputStream o = ((StreamConnection)s).openOutputStream();
InputStream i = ((StreamConnection)s).openInputStream();
o.write("hello");
Thread.sleep(sometime);
if (i.available() > 0) {
byte[] data = new data[10];
int bytesRead = i.read(data);
System.out.println("Read [" + new String(data) + "] (bytes = " + bytesRead + ")");
}
I have to comment out the if conditional for this to work.
The general contract of the InputStream.available() method is that it "Returns the number of bytes that can be read (or skipped over) from this input stream without blocking by the next caller of a method for this input stream." Hence in most implementations, it is no guarantee that it will return the Content Length of the stream that is being read. Hence it is better to read it in the following way
byte[] readFromStream(InputStream is) throws IOException
{
byte[] data = new byte[4096];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
int count = is.read(data, 0, data.length);
while (count != -1)
{
dos.write(data, 0, count);
count = is.read(data, 0, data.length);
}
data = baos.toByteArray();
return data;
}
You call the readFromStream() method and get the byte[] returned.
As I indicated in a comment above, I needed a way to determine if a device I am connecting to is not there, and I do that by seeing if our 'ping' returns any data. If the device is not there it will block. I cannot rely on that behavior. Another issue that crept up while solving this is that the read(...) methods of the RIM InputStream class block if you provide a buffer bigger than the data you want back. But how am I supposed to know how much data is there if available() returns 0? Reading byte-by-byte is about the only way to do this, but it still blocks if there is no data.
To address this I followed the theme of the 1st answer, but I put this method on its own thread and had it write to a separate byte buffer. I created a class that extended InputStream and implemented available() and read(...). Available returns how many bytes are in the byte buffer, and read only gives back however much is in the buffer or however much the caller requests, whichever is less.
This setup lets me use an InputStream interface, but behind the scenes it is just a continuously running reader thread that is alive until the connection is dropped. At that time the read, if blocked, will throw an exception to indicate the connection closed. This behavior is fine as it can be easily handled.
Thanks to all above who helped with this issue. Your thoughts help move towards the solution.
I've encountered a memory problem using FileReference.save(). My Flash application generates of a lot of data in real-time and needs to save this data to a local file. As I understand, Flash 10 (as opposed to AIR) does not support streaming to a file. But, what's even worse is that FileReference.save() duplicates all the data before saving it. I was looking for a workaround to this doubled memory usage and thought about the following approach:
What if I pass a custom subclass of ByteArray as an argument to FileReference.save(), where this ByteArray subclass would override all read*() methods. The overridden read*() methods would wait for a piece of data to be generated by my application, return this piece of data and immediately remove it from the memory. I know how much data will be generated, so I could also override length/bytesAvailable methods.
Would it be possible? Could you give me some hint how to do it? I've created a subclass of ByteArray, registered an alias for it, passed an instance of this subclass to FileReference.save(), but somehow FileReference.save() seems to treat it just as it was a ByteArray instance and doesn't call any of my overridden methods...
Thanks a lot for any help!
It's not something I've tried before, but can you try sending the data out to a php application that would handle saving the ByteArray to the server, much like saving an image to the server, so then you'd use URLLoader.data instead, using something like this:
http://www.zedia.net/2008/sending-bytearray-and-variables-to-server-side-script-at-the-same-time/
It's an interesting idea. Perhaps to start you should just add traces in your extended ByteArray to see how the FileReference#save() functions internally.
If it has some kind of
while( originalByteArray.bytesAvailable )
writeToSaveBuffer( originalByteArray.readByte() );
functionality the overrides could just truncate the original buffer on every read like you say, something like:
override function readByte() : uint {
var b : uint = super.readByte();
// Truncate the bytes (assuming bytesAvailable = length - removedBytes)
length = length - bytesAvailable;
return b;
}
On the other hand, if this now works I guess the original byte array would not be available afterwards in the application anymore.
(i havn't tested this myself, truncating might require more work than the example)