在使用QT网络通信时一直是简单的发送数据--接收数据,常见的就是发送一个字符串/字节流,然后根据这个字符串/字节流提取出有用的信息。 这样在不是很复杂的通信中可以满足实际需要。但也有弊端,就是每次写网络通信时都是口头约定一个协议,让发送方与接收方都满足这个协议才可以进行正常通信。 这样如果我每次写这样的程序,我都要首先规定好一个的通讯协议,然后再编写相应的代码。
那么如何传输更复杂的数据呢,而且可以不用上述的口头协议?
在JAVA,C#中都有对对象序列化的概念,QT里也有,利用将对象序列化传输可以对更加方便地传输我们构造的一些复杂对象数据。
The QDataStream allows you to serialize some of the Qt data types. The table below lists the data types that QDataStream can serialize and how they are represented. The format described below is version 12. It is always best to cast integers to a Qt integer type, such as qint16 or quint32, when reading and writing. This ensures that you always know exactly what size integers you are reading and writing, no matter what the underlying platform and architecture the application happens to be running on.序列化就是将一个类变成一系列的字节,利用反序列化也可以将这些字节构造出原始的这个类。这些字节可以直接存储在硬盘上,当然也可以通过网络发送出去。利用以上这些特点我们就可以开始进行一些有意思的网络通信。
当然也不是所有的类都能满足可序列化,QT 对满足序列化的类进行了说明
bool
boolean
qint8
signed byte
qint16
signed 16-bit integer
qint32
signed 32-bit integer
qint64
signed 64-bit integer
quint8
unsigned byte
quint16
unsigned 16-bit integer
quint32
unsigned 32-bit integer
quint64
unsigned 64-bit integer
float
32-bit floating point number using the standard IEEE 754 format
double
64-bit floating point number using the standard IEEE 754 format
const char *
The string length (quint32)
The string bytes, excluding the terminating 0
QBitArray
The array size (quint32)
The array bits, i.e. (size + 7)/8 bytes
QBrush
The brush style (quint8)
The brush color (QColor)
If style is CustomPattern, the brush pixmap (QPixmap)
QByteArray
If the byte array is null: 0xFFFFFFFF (quint32)
Otherwise: the array size (quint32) followed by the array bytes, i.e. size bytes
QColor
Color spec (qint8)
Alpha value (quint16)
Red value (quint16)
Green value (quint16)
Blue value (quint16)
Pad value (quint16)
QCursor
Shape ID (qint16)
If shape is BitmapCursor: The bitmap (QPixmap), mask (QPixmap), and hot spot (QPoint)
QDate
Julian day (quint32)
QDateTime
Date (QDate)
Time (QTime)
0 for Qt::LocalTime, 1 for Qt::UTC (quint8)
QEasingCurve
type (quint8)
func (quint64)
hasConfig (bool)
If hasConfig is true then these fields follow:
list
period (double)
amplitude (double)
overshoot (double)
QFont
The family (QString)
The point size (qint16)
The style hint (quint8)
The char set (quint8)
The weight (quint8)
The font bits (quint8)
QHash<Key, T>
The number of items (quint32)
For all items, the key (Key) and value (T)
QIcon
The number of pixmap entries (quint32)
For all pixmap entries:
The pixmap (QPixmap)
The file name (QString)
The pixmap size (QSize)
The mode (quint32)
The state (quint32)
QImage
If the image is null a "null image" marker is saved; otherwise the image is saved in PNG or BMP format (depending on the stream version). If you want control of the format, stream the image into a QBuffer (using QImageIO) and stream that.
QKeySequence
A QList<int>, where each integer is a key in the key sequence
QLinkedList<T>
The number of items (quint32)
The items (T)
QList<T>
The number of items (quint32)
The items (T)
QMap<Key, T>
The number of items (quint32)
For all items, the key (Key) and value (T)
QMatrix(obsolete)
m11 (double)
m12 (double)
m21 (double)
m22 (double)
dx (double)
dy (double)
QMatrix4x4
m11 (double)
m12 (double)
m13 (double)
m14 (double)
m21 (double)
m22 (double)
m23 (double)
m24 (double)
m31 (double)
m32 (double)
m33 (double)
m34 (double)
m41 (double)
m42 (double)
m43 (double)
m44 (double)
QPair<T1, T2>
first (T1)
second (T2)
QPalette The disabled, active, and inactive color groups, each of which consists of the following:
foreground (QBrush)
button (QBrush)
light (QBrush)
midlight (QBrush)
dark (QBrush)
mid (QBrush)
text (QBrush)
brightText (QBrush)
buttonText (QBrush)
base (QBrush)
background (QBrush)
shadow (QBrush)
highlight (QBrush)
highlightedText (QBrush)
link (QBrush)
linkVisited (QBrush)
QPen
The pen styles (quint8)
The pen width (quint16)
The pen color (QColor)
QPicture
The size of the picture data (quint32)
The raw bytes of picture data (char)
QPixmap
Save it as a PNG image.
QPoint
The x coordinate (qint32)
The y coordinate (qint32)
QQuaternion
The scalar component (double)
The x coordinate (double)
The y coordinate (double)
The z coordinate (double)
QRect
left (qint32)
top (qint32)
right (qint32)
bottom (qint32)
QRegExp
The regexp pattern (QString)
Case sensitivity (quint8)
Regular expression syntax (quint8)
Minimal matching (quint8)
QRegion
The size of the data, i.e. 8 + 16 * (number of rectangles) (quint32)
10 (qint32)
The number of rectangles (quint32)
The rectangles in sequential order (QRect)
QSize
width (qint32)
height (qint32)
QString
If the string is null: 0xFFFFFFFF (quint32)
Otherwise: The string length in bytes (quint32) followed by the data in UTF-16
QTime
Milliseconds since midnight (quint32)
QTransform
m11 (double)
m12 (double)
m13 (double)
m21 (double)
m22 (double)
m23 (double)
m31 (double)
m32 (double)
m33 (double)
QUrl
Holds an URL (QString)
QVariant
The type of the data (quint32)
The null flag (qint8)
The data of the specified type
QVector2D
the x coordinate (double)
the y coordinate (double)
QVector3D
the x coordinate (double)
the y coordinate (double)
the z coordinate (double)
QVector4D
the x coordinate (double)
the y coordinate (double)
the z coordinate (double)
the w coordinate (double)
QVector<T>
The number of items (quint32)
The items (T)
今天写了一个DEMO演示了一下,感觉效果还不错。
首先构造一个自己的可序列化的类
class DataPackage
{
public:
QString label_1;
QString label_2;
friend QDataStream& operator >>(QDataStream& so,DataPackage& de);
friend QDataStream& operator <<(QDataStream& de,DataPackage& so);
};
然后重载操作符
QDataStream& operator>> (QDataStream& so,DataPackage& de)
{
return so>>de.label_1>>de.label_2;
}
QDataStream& operator<< (QDataStream& de,DataPackage& so)
{
return de<<so.label_1<<so.label_2;
}
这样发送方发送的时候
void MainWindow::send_button()
{
if(!this->socketA){
this->ui->statusBar->showMessage("not a socket",5000);
return;
}
DataPackage package;
package.label_1=this->ui->A1->text();
package.label_2=this->ui->A2->text();
QByteArray by;
QDataStream ds(&by,QIODevice::WriteOnly);
ds<<package;
this->socketA->write(by);
}
接收方接收的时候
void MainWindow::socketB_recv()
{
QByteArray by= this->socketB->readAll();
QDataStream ds(&by,QIODevice::ReadOnly);
DataPackage package;
ds>>package;
this->ui->B1->setText(package.label_1);
this->ui->B2->setText(package.label_2);
}
以上轻松传递一个对象,重载的操作符<<相当与序列化这个对象。>>相当与反序列化对象。这样如果双方写协议的时候只需要构造一个协议包,然后两边分别进行序列化反序列化操作进行通信了,配合QT默认的类型将通信内容更加复杂化,使用更加便捷化。
原文:http://my.oschina.net/000quanwei/blog/412779