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

 

转载于:https://www.cnblogs.com/wanzaiyimeng/p/4572074.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/375880.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android mina分析,Android与Mina整合

最近想在自己做的安卓手机应用中加入即时聊天功能&#xff0c;于是想到了用Mina来实现&#xff0c;也是由于自己想着偷懒&#xff0c;借用了官方的example中chat的相关代码&#xff0c;经过一番改造&#xff0c;很快就能在java环境中正常运行了。确认没问题后&#xff0c;将cli…

栈的应用--括号匹配的检验

算法中设置一个栈&#xff0c;每次读入一个括号&#xff0c;若是右括号&#xff0c;则或者与置于栈顶的括号匹配&#xff0c;或者是不合法的情况&#xff0c;若是左括号&#xff0c;则入栈。若算法结束&#xff0c;栈是空的&#xff0c;则括号合法。 括号匹配函数 Status bra…

node.js 初体验

node.js 初体验 2011-10-31 22:56 by 聂微东, 174545 阅读, 118 评论, 收藏, 编辑 PS: ~ 此篇文章的进阶内容在为《Nodejs初阶之express》 ~ 2014/09/24 更新《Express 4.X 启航指南》 欢迎阅读和评论:) 最近写的文章收到许多朋友的反馈&#xff0c;感谢大家的支持和建议&#…

Qt之模型/视图(实时更新数据)

上两节简单介绍了Qt中对于模型/视图的编程&#xff0c;大部分助手里说的很清楚了&#xff0c;现在就开始实战部分吧&#xff01; 在实际应用中&#xff0c;视图展示的数据往往并非一成不变的&#xff0c;那么如何实时更新成了一个很重要的问题&#xff01;功能&#xff1a;&am…

android 动态生成fragment,Android动态加载fragment(fragment复用)

【实例简介】Android动态加载fragment(fragment复用)【实例截图】【核心代码】fm_reuse└── fm_reuse├── AndroidManifest.xml├── bin│ ├── AndroidManifest.xml│ ├── classes│ │ └── com│ │ └── example│ │ └── fm_reuse│ …

Linux内核3.0移植并基于Initramfs根文件系统启动

Linux内核移植与启动 Target borad&#xff1a;FL2440 Bootloader&#xff1a;U-boot-2010.09 交叉编译器&#xff1a;buildroot-2012.08 1.linux内核基础知识 首先&#xff0c;磨刀不误砍柴工。在动手进行linux内核移植之前&#xff0c;我们有必要对linux内核进行一定的了解。…

操作系统上机作业--实现shell(2)(多进程)

sh2.c: 实现shell程序&#xff0c;要求在第1版的基础上&#xff0c;添加如下功能 • 实现文件重定向 • $ echo hello >log • $ cat log • Hello 实现思路&#xff1a; 和sh1.c相比&#xff0c;主要是修改了cmd函数的实现过程。通过循环找出重定向符号"&g…

当泛型方法推断,扩展方法遇到泛型类型in/out时。。。

说到泛型方法&#xff0c;这个是.net 2.0的时候引入的一个重要功能&#xff0c;c#2.0也对此作了非常好的支持&#xff0c;可以不需要显试的声明泛型类型&#xff0c;让编译器自动推断&#xff0c;例如&#xff1a; 1 void F<T>(T value){} 2 //... 3 int i 0; 4 F(i); 此…

AOP相关

实现AOP的技术&#xff0c;主要分为两大类&#xff1a;一是采用动态代理技术&#xff0c;利用截取消息的方式&#xff0c;对该消息进行装饰&#xff0c;以取代原有对象行为的执行&#xff1b;二是采用静态织入的方式&#xff0c;引入特定的语法创建“方面”&#xff0c;从而使得…

操作系统上机作业--根据莱布尼兹级数计算PI(1)(多线程)

pi1.c: 使用2个线程根据莱布尼兹级数计算PI • 莱布尼兹级数公式: 1 - 1/3 1/5 - 1/7 1/9 - ... PI/4 • 主线程创建1个辅助线程 • 主线程计算级数的前半部分 • 辅助线程计算级数的后半部分 • 主线程等待辅助线程运行結束后,将前半部分和后半部分相加实现思路&#xff1…

四种途径将HTML5 web应用变成android应用

作为下一代的网页语言&#xff0c;HTML5拥有很多让人期待已久的新特性。HTML5的优势之一在于能够实现跨平台游戏编码移植&#xff0c;现在已经有很多公司在移动设备上使用HTML5技术。随着HTML5跨平台支持的不断增强和智能手机的迅速普&#xff0c;HTML5技术有着非常好的发展前景…

操作系统上机作业--根据莱布尼兹级数计算PI(2)(多线程)

pi2.c: 使用N个线程根据莱布尼兹级数计算PI • 与上一题类似&#xff0c;但本题更加通用化&#xff0c;能适应N个核心&#xff0c;需要使用线程参数来实现 • 主线程创建N个辅助线程 • 每个辅助线程计算一部分任务&#xff0c;并将结果返回 • 主线程等待N个辅助线程…

html 16进制 转换成字符串,js 字符串和16进制的互相转换

字符串转16进制function strToHexCharCode(str) {if(str "")return "";var hexCharCode [];hexCharCode.push("0x");for(var i 0; i < str.length; i) {hexCharCode.push((str.charCodeAt(i)).toString(16));}return hexCharCode.join(&qu…

数组以及冒泡排序

数组 1、概念&#xff1a;可以帮我一次声明多个同类型的变量&#xff0c;这些变量再内存中是连续存储的。 2、声明语法&#xff1a;数据类型[] 数组名 new 数据类型[数组长度] 数组长度&#xff1a;一次要声明的同类型的变量个数。是在定义这个数组的时候就确定了&#xf…

jQuery触发a标签的点击事件无效

1 <a id"workFrame" href"pages/work.html" target"FrameBox">首页</a> 2 3 $("#workFrame").tigger("click"); 上述的代码&#xff0c;其实挺正常的&#xff0c;但是怎么也触发不了a标签的cli…

操作系统上机作业--多线程排序

sort.c: 多线程排序 • 主线程创建一个辅助线程 • 主线程使用选择排序算法对数组的前半部分排序 • 辅助线程使用选择排序算法对数组的后半部分排序 • 主线程等待辅助线程运行結束后,使用归并排序算法归并数组的前半部分和后半部分 实现思路&#xff1a; ARRAY_CO…

jdk5下载链接

查看jdk版本 java -versionJDK下载 最新版本http://www.oracle.com/technetwork/java/javase/downloads/index.htmlJDK下载 版本1.5.22http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase5-419410.html#jdk-1.5.0_22-oth-JPR JDK…

html的细节优化,网站页面优化细节详解

原标题&#xff1a;网站页面优化细节详解SEO页面优化是继SEO结构优化之后&#xff0c;另一个重要优化地方;页面标题在每个页面中的关键位置&#xff0c;出现目标关键词&#xff0c;这是我们做页面优化的基础思路&#xff0c;关键词位置&#xff0c;都有哪些呢?第一个是关键位置…

突击优化算法!

Matlab语言可以与C/C语言转换或调用。 Matlab语句&#xff1a;load name 把name中文件的所有变量载入到工作空间中。save name 保存工作空间的变量到name.mat中。 cholesky分解把一个正定矩阵分为一个下三角矩阵和它转置矩阵的乘积。 两种创立符号函数的方法&#xff1a;sym函数…

操作系统上机作业--使用条件变量解决生产者、计算者、消费者问题(多线程)

pc1.c: 使用条件变量解决生产者、计算者、消费者问题 /* • 系统中有3个线程&#xff1a;生产者、计算者、消费者 • 系统中有2个容量为4的缓冲区&#xff1a;buffer1、buffer2 • 生产者生产a、b、c、‘d、e、f、g、h八个字符&#xff0c;放入到buffer1 • 计算者从b…