基于QTcpSocket和QTcpServer的Tcp通讯以及QDataStream序列化数据

来源:互联网 发布:ubuntu进不去系统 编辑:程序博客网 时间:2024/06/05 08:36
最近要在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_Motor13 {14     int length;15     int command;16     QString data;17 };18 19 20 class Motor21 {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 QMainWindow68 {69     Q_OBJECT70 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     //out103     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 QMainWindow14 {15     Q_OBJECT16 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 Motor16 {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 QTcpServer50 {51     Q_OBJECT52 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.重载的时候一定要正确。

 


源代码连接:http://download.csdn.net/detail/cmp15845953187/8800409

0 0
原创粉丝点击