zoukankan      html  css  js  c++  java
  • 基于QTcpSocket和QTcpServer的Tcp通讯以及QDataStream序列化数据

    最近要在QT下开发Tcp通讯,发送序列化数据以便于接收。

    这里涉及到几个问题:

    1.QTcpSocket、QTcpServer的通讯

    2.QDataStream序列化数据

    多的不说,直接上干货!!!

    客户端:

    tcpclient.h

     1 #ifndef TCPCLIENT_H
     2 #define TCPCLIENT_H
     3 
     4 #include <QMainWindow>
     5 #include <qt4/Qt/qtcpsocket.h>
     6 #include <Qt/qhostinfo.h>
     7 #include <QDataStream>
     8 #include <QtNetwork>
     9 
    10 
    11 
    12 struct Control_Motor
    13 {
    14     int length;
    15     int command;
    16     QString data;
    17 };
    18 
    19 
    20 class Motor
    21 {
    22 public:
    23     Motor(){}
    24     Motor(int speed,int accele_speed,int p_some)
    25     {
    26         m_speed = speed;
    27         m_accele_speed = accele_speed;
    28         m_p_some = p_some;
    29     }
    30 
    31 
    32 
    33 public:
    34     int getV(){return m_speed;}
    35     int getA(){return m_accele_speed;}
    36     int getP(){return m_p_some;}
    37 
    38     void setV(const int v){m_speed = v;}
    39     void setA(const int a){m_accele_speed = a;}
    40     void setP(const int p){m_p_some = p;}
    41 
    42 
    43 
    44 public:
    45     //friend QDataStream & operator <<(QDataStream &out,const Motor &motor);
    46     //friend QDataStream & operator >>(QDataStream &in,Motor &motor);
    47     /*
    48     friend QDataStream & operator <<(QDataStream &out,Motor &motor)
    49     {
    50         out << motor.m_speed<<motor.m_p_some<<motor.m_accele_speed;
    51         qDebug()<< motor.m_speed<<motor.m_p_some<<motor.m_accele_speed<<"Enter in this";
    52         return out;
    53     }
    54     */
    55 public:
    56     int m_speed;
    57     int m_accele_speed;
    58     int m_p_some;
    59 
    60 };
    61 
    62 
    63 namespace Ui {
    64 class TcpClient;
    65 }
    66 
    67 class TcpClient : public QMainWindow
    68 {
    69     Q_OBJECT
    70 
    71 public:
    72     explicit TcpClient(QWidget *parent = 0);
    73     ~TcpClient();
    74 
    75 private:
    76     Ui::TcpClient *ui;
    77     QTcpSocket *tcpClient;
    78 
    79 
    80 private slots:
    81     void slotConnect();
    82     void readMessage();
    83     void displayError(QAbstractSocket::SocketError);
    84     void sendMessage();
    85 
    86 
    87 
    88 public:
    89     Control_Motor control_Motor;
    90 
    91     Motor *m_motor;
    92 
    93 };
    94 
    95 
    96 #endif // TCPCLIENT_H 

    tcpclient.cpp

      1 #include "tcpclient.h"
      2 #include "ui_tcpclient.h"
      3 #include <QFile>
      4 #include <QDataStream>
      5 
      6 
      7 QDataStream & operator<<(QDataStream &out,const Motor &motor)
      8 {
      9     //qDebug()<< motor.m_speed<<motor.m_p_some<<motor.m_accele_speed<<"Enter in";
     10     out << motor.m_speed<<motor.m_p_some<<motor.m_accele_speed;
     11     //qDebug()<< motor.m_speed<<motor.m_p_some<<motor.m_accele_speed<<"Enter in this";
     12     return out;
     13 }
     14 
     15 QDataStream &operator >>(QDataStream &in,Motor &motor)
     16 {
     17     int speed = 0;
     18     int accele_speed =0;
     19     int p_some = 0;
     20 
     21     in >> speed >> p_some >> accele_speed;
     22 
     23     motor.setV(speed);
     24     motor.setP(p_some);
     25     motor.setA(accele_speed);
     26 
     27     return in;
     28 }
     29 Q_DECLARE_METATYPE(Motor)
     30 
     31 
     32 TcpClient::TcpClient(QWidget *parent) :
     33     QMainWindow(parent),
     34     ui(new Ui::TcpClient)
     35 {
     36     ui->setupUi(this);
     37 
     38     qRegisterMetaType<Motor>("Motor");
     39 
     40     tcpClient = new QTcpSocket(this);
     41     connect(ui->Connect_Btn,SIGNAL(clicked()),this,SLOT(slotConnect()));
     42     connect(ui->Send_Btn,SIGNAL(clicked()),this,SLOT(sendMessage()));
     43     connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readMessage()));
     44     connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), this,
     45                 SLOT(displayError(QAbstractSocket::SocketError)));
     46 }
     47 
     48 TcpClient::~TcpClient()
     49 {
     50     delete ui;
     51 }
     52 
     53 void TcpClient::slotConnect()
     54 {
     55     //QString stringAddress = ui->ldt_IP->text();
     56     //QString stringPort = ui->ldt_Port->text();
     57     QString stringAddress = "192.168.154.128";
     58     QString stringPort = "8080";
     59     int port = stringPort.toInt();
     60     QHostAddress address;
     61     address.setAddress(stringAddress);
     62     tcpClient->abort();
     63     tcpClient->connectToHost(address,port);
     64     ui->Connect_Btn->setEnabled(false);
     65 }
     66 
     67 void TcpClient::readMessage()
     68 {
     69 
     70 }
     71 
     72 void TcpClient::displayError(QAbstractSocket::SocketError)
     73 {
     74    qDebug() << tcpClient->errorString();
     75 }
     76 
     77 void TcpClient::sendMessage()
     78 {
     79     QString stringMotor = ui->ldt_Motor->text();
     80     QString stringData = ui->ldt_data->text();
     81     control_Motor.command = stringMotor.toInt();
     82     int dataLength = stringData.length();
     83     control_Motor.length = 8 + dataLength;
     84     control_Motor.data = stringData;
     85     QString data = stringMotor+stringData;
     86 
     87     m_motor = new Motor(20,40,60);
     88 
     89     //Motor m_motor(20,40,60);
     90 
     91     //用于暂存要发送的数据
     92     QByteArray block;
     93     //使用数据流写入数据
     94     QDataStream out(&block,QIODevice::WriteOnly);
     95     //设置数据流的版本,客户端和服务器端使用的版本要相同
     96     out.setVersion(QDataStream::Qt_4_6);
     97     out<<(quint32) 0;
     98     //设置发送长度初始值为0
     99     //out << control_Motor.length<<control_Motor.command<<control_Motor.data;
    100 
    101     //qDebug() << control_Motor.length<<control_Motor.command<<control_Motor.data;
    102     //out
    103     out << control_Motor.command;
    104     qDebug()<<"Start out"<<endl;
    105     out << *m_motor;
    106     qDebug()<<"End out"<<endl;
    107     qDebug() << control_Motor.command<< m_motor->getA()<<m_motor->getP()<<m_motor->getV();
    108     //回到字节流起始位置
    109     out.device()->seek(0);
    110     //重置字节流长度
    111     //out << (quint16) (block.size()-sizeof(quint16));
    112     out << (quint32)(block.size()- sizeof(quint32));
    113     qDebug() << "block.size()"<<block.size();
    114 
    115     //往套接字缓存中写入数据,并发送
    116     tcpClient->write(block,block.size());
    117     tcpClient->disconnectFromHost();
    118     tcpClient->waitForDisconnected();
    119 
    120     block.resize(0);
    121     this->close();
    122     //tcpClient->write(data.toLatin1(),data.size());
    123 }

    服务器端:

    tcpserver.h

     1 ifndef TCPSERVER_H
     2 #define TCPSERVER_H
     3 
     4 #include <QMainWindow>
     5 #include <qt4/Qt/qhostinfo.h>
     6 #include "server.h"
     7 
     8 
     9 namespace Ui {
    10 class TcpServer;
    11 }
    12 
    13 class TcpServer : public QMainWindow
    14 {
    15     Q_OBJECT
    16 
    17 public:
    18     explicit TcpServer(QWidget *parent = 0);
    19     ~TcpServer();
    20 
    21 private:
    22     Ui::TcpServer *ui;
    23     int port;
    24     Server *server;
    25 
    26 protected slots:
    27     void slotCreateServer();
    28     void updateServer(QString,int);
    29 
    30 };
    31 
    32 #endif // TCPSERVER_H

    tcpserver.cpp

     1 #include "tcpserver.h"
     2 #include "ui_tcpserver.h"
     3 #include <QtNetwork/QNetworkInterface>
     4 
     5 TcpServer::TcpServer(QWidget *parent) :
     6     QMainWindow(parent),
     7     ui(new Ui::TcpServer)
     8 {
     9     ui->setupUi(this);
    10     port = 8080;
    11     QString address = QNetworkInterface::allAddresses().first().toString();
    12     QList<QHostAddress> list2 = QNetworkInterface::allAddresses();
    13     foreach (QHostAddress address, list2)
    14     {
    15         if(address.protocol() == QAbstractSocket::IPv4Protocol)
    16             ui->ldt_IP->setText(address.toString());
    17     }
    18     ui->ldt_Port->setText(QString::number(port));
    19     connect(ui->Connect_Btn,SIGNAL(clicked()),this,SLOT(slotCreateServer()));
    20 }
    21 
    22 TcpServer::~TcpServer()
    23 {
    24     delete ui;
    25 }
    26 
    27 void TcpServer::slotCreateServer()
    28 {
    29     server = new Server(this,port);
    30     connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int)));
    31     ui->Connect_Btn->setEnabled(false);
    32 }
    33 
    34 void TcpServer::updateServer(QString msg, int length)
    35 {
    36     ui->lwt_Text->addItem(msg.left(length));
    37 }

    server.h

     1 #ifndef SERVER_H
     2 #define SERVER_H
     3 
     4 #include <qt4/Qt/qtcpserver.h>
     5 #include <qt4/Qt/qtcpsocket.h>
     6 
     7 struct Control_Motor
     8 {
     9     int length;
    10     int command;
    11     QString data;
    12 };
    13 
    14 
    15 class Motor
    16 {
    17 public:
    18     Motor(int speed,int accele_speed,int p_some)
    19     {
    20         m_speed = speed;
    21         m_accele_speed = accele_speed;
    22         m_p_some = p_some;
    23     }
    24 
    25     Motor(){m_speed = 0;}
    26 
    27 
    28 
    29 public:
    30     int getV(){return m_speed;}
    31     int getA(){return m_accele_speed;}
    32     int getP(){return m_p_some;}
    33 
    34     void setV(const int v){m_speed = v;}
    35     void setA(const int a){m_accele_speed = a;}
    36     void setP(const int p){m_p_some = p;}
    37 
    38 
    39 
    40 private:
    41     int m_speed;
    42     int m_accele_speed;
    43     int m_p_some;
    44 
    45 };
    46 
    47 
    48 
    49 class Server : public QTcpServer
    50 {
    51     Q_OBJECT
    52 
    53 public:
    54     Server(QObject *parents=0,int port=0);
    55     QList<QTcpSocket*>TcpClientSocketList;
    56     QTcpSocket *tcpClientSocket;
    57 signals:
    58     void updateServer(QString,int);
    59 
    60 public slots:
    61     void slotUpdateClient(QString,int);
    62     void slotDisconnect(int);
    63 //    void slotnewconnection();
    64 protected:
    65     void incomingConnection(int socketDescriptor);
    66 
    67 signals:
    68     void updateClients(QString,int);
    69     void disconnected(int);
    70 
    71 protected slots:
    72     void dataReceive();
    73     void slotDisconnected();
    74 
    75 public:
    76     Control_Motor control_motor;
    77     Motor m_mtor;
    78 };
    79 
    80 #endif // SERVER_H

    server.cpp

      1 #include "server.h"
      2 
      3 QDataStream &operator <<(QDataStream &out,Motor &motor)
      4 {
      5     out << motor.getV()<<motor.getP()<<motor.getA();
      6     return out;
      7 }
      8 
      9 
     10 QDataStream &operator >>(QDataStream &in,Motor &motor)
     11 {
     12     int speed = motor.getV();
     13     int accele_speed =motor.getA();
     14     int p_some = motor.getP();
     15 
     16     in >> speed >> p_some >> accele_speed;
     17 
     18     motor.setV(speed);
     19     motor.setP(p_some);
     20     motor.setA(accele_speed);
     21 
     22     return in;
     23 }
     24 
     25 
     26 
     27 
     28 Server::Server(QObject *parent,int port) :
     29     QTcpServer(parent)
     30 {
     31     this->listen(QHostAddress::Any,port);
     32 }
     33 
     34 void Server::incomingConnection(int socketDescriptor)
     35 {
     36     tcpClientSocket = new QTcpSocket(this);
     37     //tcpClientSocket = this->nextPendingConnection();
     38     tcpClientSocket->setSocketDescriptor(socketDescriptor);
     39     TcpClientSocketList.append(tcpClientSocket);
     40     //connect(this,SIGNAL(updateClients(QString,int)),this,SLOT(slotUpdateClient(QString,int)));
     41     //connect(this,SIGNAL(updateClients(QString,int)),this,SLOT(slotUpdateClient(QString,int)));
     42     connect(this,SIGNAL(disconnected(int)),this,SLOT(slotDisconnect(int)));
     43     connect(tcpClientSocket,SIGNAL(readyRead()),this,SLOT(dataReceive()));
     44     connect(tcpClientSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
     45     //connect(tcpClientSocket,SIGNAL(disconnected()),tcpClientSocket,SLOT(deleteLater()));
     46 
     47 }
     48 void Server::slotUpdateClient(QString msg,int length)
     49 {
     50     emit updateServer(msg,length);
     51     for (int i=0;i<TcpClientSocketList.count();i++)
     52     {
     53         QTcpSocket *item=TcpClientSocketList.at(i);
     54         if (item->write(msg.toLatin1(),length)!=length)
     55             continue;
     56     }
     57 }
     58 void Server::slotDisconnect(int socketDescriptor)
     59 {
     60     qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<endl;
     61     for (int i=0;i<TcpClientSocketList.count();i++)
     62      if (TcpClientSocketList.at(i)->socketDescriptor()==socketDescriptor)
     63      {
     64            TcpClientSocketList.removeAt(i);
     65             return;
     66      }
     67 }
     68 
     69 void Server::dataReceive()
     70 {
     71     qDebug()<<"QQWQW11111111111111";
     72     //quint32 size = 0;
     73     quint32 nextBlockSize = 0;
     74     qDebug()<<"TcpClientSocketList.count()"<<TcpClientSocketList.count();
     75     //for(int i = 0; i < TcpClientSocketList.count();i++)
     76     //{
     77         QDataStream in(tcpClientSocket);
     78         in.setVersion(QDataStream::Qt_4_6);
     79        if(nextBlockSize == 0)
     80        {
     81            if(tcpClientSocket->bytesAvailable()<sizeof(quint32))
     82            {
     83                //break;
     84                return;
     85            }
     86            in>>nextBlockSize;
     87            qDebug()<<nextBlockSize;
     88        }
     89        if(nextBlockSize==0xFFFF)
     90        {
     91            //break;
     92            return;
     93        }
     94        if(tcpClientSocket->bytesAvailable()<nextBlockSize)
     95        {
     96            //break;
     97            return;
     98        }
     99 
    100        //in>>control_motor.length>>control_motor.command>>control_motor.data;
    101 
    102        //qDebug()<<control_motor.length<<control_motor.command<<control_motor.data;
    103        in >>control_motor.command >> m_mtor;
    104        qDebug()<<control_motor.command<< m_mtor.getA()<<m_mtor.getP()<<m_mtor.getV();
    105 
    106        //ui->SN_lineEdit_2->setText(QString("%1").arg(message_rev.SN));
    107        //ui->IP_lineEdit->setText(message_rev.IP);
    108        //ui->STATE_lineEdit_3->setText(message_rev.Condition);
    109     //}
    110 }
    111 
    112 void Server::slotDisconnected()
    113 {
    114     qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<endl;
    115     emit disconnected(tcpClientSocket->socketDescriptor());
    116 }

    在这里要特别说明一下,在此遇到的几个问题,希望能帮到大家,也提醒一下自己。

    1.在TcpClient.pro,TcpServer.pro里一定要注意加上QT += network,不然编译的时候QNetworkInterface、QHostAddress这些地方会报错误。

    2.在QDataStream重载自定义的类的时候,一开始把重载写在.h文件里编译的时候总是报Tcp_DataStream/TcpServer/server.h:49: error: multiple definition of `operator<<(QDataStream&, Motor&)'这个错误,说实话这个问题真的困扰了我很久,然后把重载函数放到.cpp文件里,编译通过,简直是要命

    3.QDataStream的nextBlock读取到的长度为发送的数据的长度(而不是整个包的长度out << (quint32)(block.size()- sizeof(quint32));),如果直接写out << (quint32)(block.size()),读的时候数据将会不正常。

    4.重载的时候一定要正确。

  • 相关阅读:
    GL_TRIANGLE_FAN Vs GL_TRIANGLE_STRIP
    Color bleeding与caustics概念解析
    Two path ray tracing与Photon Mapping(粒子跟踪)
    右手定则判断法线方向
    正确使用atoi
    深入探讨透视投影坐标变换
    gluBuild2DMipmaps与glTexImage2D与glGenTexture()函数
    OpenGL纹理贴图流程
    int main( int argc, char ** argv)在VS2008中的配置的一个实例
    c++标准库中vector数组遍历时的用法
  • 原文地址:https://www.cnblogs.com/wanzaiyimeng/p/4572074.html
Copyright © 2011-2022 走看看