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

 

 

 

 

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

转载于:https://my.oschina.net/qtplus/blog/1942299

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值