基于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.重载的时候一定要正确。

 

posted @ 2015-06-12 16:51  万载一梦  阅读(5712)  评论(0编辑  收藏  举报