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

这里涉及到几个问题:

1.QTcpSocket、QTcpServer的通讯

2.QDataStream序列化数据

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

客户端:

tcpclient.h

 #ifndef TCPCLIENT_H
#define TCPCLIENT_H #include <QMainWindow>
#include <qt4/Qt/qtcpsocket.h>
#include <Qt/qhostinfo.h>
#include <QDataStream>
#include <QtNetwork> struct Control_Motor
{
int length;
int command;
QString data;
}; class Motor
{
public:
Motor(){}
Motor(int speed,int accele_speed,int p_some)
{
m_speed = speed;
m_accele_speed = accele_speed;
m_p_some = p_some;
} public:
int getV(){return m_speed;}
int getA(){return m_accele_speed;}
int getP(){return m_p_some;} void setV(const int v){m_speed = v;}
void setA(const int a){m_accele_speed = a;}
void setP(const int p){m_p_some = p;} public:
//friend QDataStream & operator <<(QDataStream &out,const Motor &motor);
//friend QDataStream & operator >>(QDataStream &in,Motor &motor);
/*
friend QDataStream & operator <<(QDataStream &out,Motor &motor)
{
out << motor.m_speed<<motor.m_p_some<<motor.m_accele_speed;
qDebug()<< motor.m_speed<<motor.m_p_some<<motor.m_accele_speed<<"Enter in this";
return out;
}
*/
public:
int m_speed;
int m_accele_speed;
int m_p_some; }; namespace Ui {
class TcpClient;
} class TcpClient : public QMainWindow
{
Q_OBJECT public:
explicit TcpClient(QWidget *parent = );
~TcpClient(); private:
Ui::TcpClient *ui;
QTcpSocket *tcpClient; private slots:
void slotConnect();
void readMessage();
void displayError(QAbstractSocket::SocketError);
void sendMessage(); public:
Control_Motor control_Motor; Motor *m_motor; }; #endif // TCPCLIENT_H

tcpclient.cpp

 #include "tcpclient.h"
#include "ui_tcpclient.h"
#include <QFile>
#include <QDataStream> QDataStream & operator<<(QDataStream &out,const Motor &motor)
{
//qDebug()<< motor.m_speed<<motor.m_p_some<<motor.m_accele_speed<<"Enter in";
out << motor.m_speed<<motor.m_p_some<<motor.m_accele_speed;
//qDebug()<< motor.m_speed<<motor.m_p_some<<motor.m_accele_speed<<"Enter in this";
return out;
} QDataStream &operator >>(QDataStream &in,Motor &motor)
{
int speed = ;
int accele_speed =;
int p_some = ; in >> speed >> p_some >> accele_speed; motor.setV(speed);
motor.setP(p_some);
motor.setA(accele_speed); return in;
}
Q_DECLARE_METATYPE(Motor) TcpClient::TcpClient(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TcpClient)
{
ui->setupUi(this); qRegisterMetaType<Motor>("Motor"); tcpClient = new QTcpSocket(this);
connect(ui->Connect_Btn,SIGNAL(clicked()),this,SLOT(slotConnect()));
connect(ui->Send_Btn,SIGNAL(clicked()),this,SLOT(sendMessage()));
connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readMessage()));
connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), this,
SLOT(displayError(QAbstractSocket::SocketError)));
} TcpClient::~TcpClient()
{
delete ui;
} void TcpClient::slotConnect()
{
//QString stringAddress = ui->ldt_IP->text();
//QString stringPort = ui->ldt_Port->text();
QString stringAddress = "192.168.154.128";
QString stringPort = "";
int port = stringPort.toInt();
QHostAddress address;
address.setAddress(stringAddress);
tcpClient->abort();
tcpClient->connectToHost(address,port);
ui->Connect_Btn->setEnabled(false);
} void TcpClient::readMessage()
{ } void TcpClient::displayError(QAbstractSocket::SocketError)
{
qDebug() << tcpClient->errorString();
} void TcpClient::sendMessage()
{
QString stringMotor = ui->ldt_Motor->text();
QString stringData = ui->ldt_data->text();
control_Motor.command = stringMotor.toInt();
int dataLength = stringData.length();
control_Motor.length = + dataLength;
control_Motor.data = stringData;
QString data = stringMotor+stringData; m_motor = new Motor(,,); //Motor m_motor(20,40,60); //用于暂存要发送的数据
QByteArray block;
//使用数据流写入数据
QDataStream out(&block,QIODevice::WriteOnly);
//设置数据流的版本,客户端和服务器端使用的版本要相同
out.setVersion(QDataStream::Qt_4_6);
out<<(quint32) ;
//设置发送长度初始值为0
//out << control_Motor.length<<control_Motor.command<<control_Motor.data; //qDebug() << control_Motor.length<<control_Motor.command<<control_Motor.data;
//out
out << control_Motor.command;
qDebug()<<"Start out"<<endl;
out << *m_motor;
qDebug()<<"End out"<<endl;
qDebug() << control_Motor.command<< m_motor->getA()<<m_motor->getP()<<m_motor->getV();
//回到字节流起始位置
out.device()->seek();
//重置字节流长度
//out << (quint16) (block.size()-sizeof(quint16));
out << (quint32)(block.size()- sizeof(quint32));
qDebug() << "block.size()"<<block.size(); //往套接字缓存中写入数据,并发送
tcpClient->write(block,block.size());
tcpClient->disconnectFromHost();
tcpClient->waitForDisconnected(); block.resize();
this->close();
//tcpClient->write(data.toLatin1(),data.size());
}

服务器端:

tcpserver.h

 ifndef TCPSERVER_H
#define TCPSERVER_H #include <QMainWindow>
#include <qt4/Qt/qhostinfo.h>
#include "server.h" namespace Ui {
class TcpServer;
} class TcpServer : public QMainWindow
{
Q_OBJECT public:
explicit TcpServer(QWidget *parent = );
~TcpServer(); private:
Ui::TcpServer *ui;
int port;
Server *server; protected slots:
void slotCreateServer();
void updateServer(QString,int); }; #endif // TCPSERVER_H

tcpserver.cpp

 #include "tcpserver.h"
#include "ui_tcpserver.h"
#include <QtNetwork/QNetworkInterface> TcpServer::TcpServer(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TcpServer)
{
ui->setupUi(this);
port = ;
QString address = QNetworkInterface::allAddresses().first().toString();
QList<QHostAddress> list2 = QNetworkInterface::allAddresses();
foreach (QHostAddress address, list2)
{
if(address.protocol() == QAbstractSocket::IPv4Protocol)
ui->ldt_IP->setText(address.toString());
}
ui->ldt_Port->setText(QString::number(port));
connect(ui->Connect_Btn,SIGNAL(clicked()),this,SLOT(slotCreateServer()));
} TcpServer::~TcpServer()
{
delete ui;
} void TcpServer::slotCreateServer()
{
server = new Server(this,port);
connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString,int)));
ui->Connect_Btn->setEnabled(false);
} void TcpServer::updateServer(QString msg, int length)
{
ui->lwt_Text->addItem(msg.left(length));
}

server.h

 #ifndef SERVER_H
#define SERVER_H #include <qt4/Qt/qtcpserver.h>
#include <qt4/Qt/qtcpsocket.h> struct Control_Motor
{
int length;
int command;
QString data;
}; class Motor
{
public:
Motor(int speed,int accele_speed,int p_some)
{
m_speed = speed;
m_accele_speed = accele_speed;
m_p_some = p_some;
} Motor(){m_speed = ;} public:
int getV(){return m_speed;}
int getA(){return m_accele_speed;}
int getP(){return m_p_some;} void setV(const int v){m_speed = v;}
void setA(const int a){m_accele_speed = a;}
void setP(const int p){m_p_some = p;} private:
int m_speed;
int m_accele_speed;
int m_p_some; }; class Server : public QTcpServer
{
Q_OBJECT public:
Server(QObject *parents=,int port=);
QList<QTcpSocket*>TcpClientSocketList;
QTcpSocket *tcpClientSocket;
signals:
void updateServer(QString,int); public slots:
void slotUpdateClient(QString,int);
void slotDisconnect(int);
// void slotnewconnection();
protected:
void incomingConnection(int socketDescriptor); signals:
void updateClients(QString,int);
void disconnected(int); protected slots:
void dataReceive();
void slotDisconnected(); public:
Control_Motor control_motor;
Motor m_mtor;
}; #endif // SERVER_H

server.cpp

 #include "server.h"

 QDataStream &operator <<(QDataStream &out,Motor &motor)
{
out << motor.getV()<<motor.getP()<<motor.getA();
return out;
} QDataStream &operator >>(QDataStream &in,Motor &motor)
{
int speed = motor.getV();
int accele_speed =motor.getA();
int p_some = motor.getP(); in >> speed >> p_some >> accele_speed; motor.setV(speed);
motor.setP(p_some);
motor.setA(accele_speed); return in;
} Server::Server(QObject *parent,int port) :
QTcpServer(parent)
{
this->listen(QHostAddress::Any,port);
} void Server::incomingConnection(int socketDescriptor)
{
tcpClientSocket = new QTcpSocket(this);
//tcpClientSocket = this->nextPendingConnection();
tcpClientSocket->setSocketDescriptor(socketDescriptor);
TcpClientSocketList.append(tcpClientSocket);
//connect(this,SIGNAL(updateClients(QString,int)),this,SLOT(slotUpdateClient(QString,int)));
//connect(this,SIGNAL(updateClients(QString,int)),this,SLOT(slotUpdateClient(QString,int)));
connect(this,SIGNAL(disconnected(int)),this,SLOT(slotDisconnect(int)));
connect(tcpClientSocket,SIGNAL(readyRead()),this,SLOT(dataReceive()));
connect(tcpClientSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
//connect(tcpClientSocket,SIGNAL(disconnected()),tcpClientSocket,SLOT(deleteLater())); }
void Server::slotUpdateClient(QString msg,int length)
{
emit updateServer(msg,length);
for (int i=;i<TcpClientSocketList.count();i++)
{
QTcpSocket *item=TcpClientSocketList.at(i);
if (item->write(msg.toLatin1(),length)!=length)
continue;
}
}
void Server::slotDisconnect(int socketDescriptor)
{
qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<endl;
for (int i=;i<TcpClientSocketList.count();i++)
if (TcpClientSocketList.at(i)->socketDescriptor()==socketDescriptor)
{
TcpClientSocketList.removeAt(i);
return;
}
} void Server::dataReceive()
{
qDebug()<<"QQWQW11111111111111";
//quint32 size = 0;
quint32 nextBlockSize = ;
qDebug()<<"TcpClientSocketList.count()"<<TcpClientSocketList.count();
//for(int i = 0; i < TcpClientSocketList.count();i++)
//{
QDataStream in(tcpClientSocket);
in.setVersion(QDataStream::Qt_4_6);
if(nextBlockSize == )
{
if(tcpClientSocket->bytesAvailable()<sizeof(quint32))
{
//break;
return;
}
in>>nextBlockSize;
qDebug()<<nextBlockSize;
}
if(nextBlockSize==0xFFFF)
{
//break;
return;
}
if(tcpClientSocket->bytesAvailable()<nextBlockSize)
{
//break;
return;
} //in>>control_motor.length>>control_motor.command>>control_motor.data; //qDebug()<<control_motor.length<<control_motor.command<<control_motor.data;
in >>control_motor.command >> m_mtor;
qDebug()<<control_motor.command<< m_mtor.getA()<<m_mtor.getP()<<m_mtor.getV(); //ui->SN_lineEdit_2->setText(QString("%1").arg(message_rev.SN));
//ui->IP_lineEdit->setText(message_rev.IP);
//ui->STATE_lineEdit_3->setText(message_rev.Condition);
//}
} void Server::slotDisconnected()
{
qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<endl;
emit disconnected(tcpClientSocket->socketDescriptor());
}

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

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

基于QTcpSocket和QTcpServer的Tcp通讯以及QDataStream序列化数据的更多相关文章

  1. .Net开发笔记(十五) 基于“泵”的TCP通讯(接上篇)

    上一篇博客中说了基于“泵”的UDP通讯,附上了一个Demo,模拟飞鸽传书的功能,功能不太完善,主要是为了说明“泵”在编程中的应用.本篇文章我再附上一个关于TCP通讯的两个Demo,也都采用了“泵”模式 ...

  2. 基于“泵”的TCP通讯(接上篇)

    基于“泵”的TCP通讯(接上篇) 上一篇博客中说了基于“泵”的UDP通讯,附上了一个Demo,模拟飞鸽传书的功能,功能不太完善,主要是为了说明“泵”在编程中的应用.本篇文章我再附上一个关于TCP通讯的 ...

  3. wp8使用Beetle.NetPackage实现基于TCP通讯的订单查询

    在新版本的Beetle.NetPackage中提供了对Protobuf和Controller的支持,所以在WP8下使用Beetle.NetPackage进行基于TCP的数据交互则一件非常简单事情.下面 ...

  4. 基于STM32和W5500的Modbus TCP通讯

    在最近的一个项目中需要实现Modbus TCP通讯,而选用的硬件平台则是STM32F103和W5500,软件平台则选用IAR EWAR6.4来实现. 1.移植千的准备工作 为了实现Modbus TCP ...

  5. QTcpSocket-Qt使用Tcp通讯实现服务端和客户端

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QTcpSocket-Qt使用Tcp通讯实现服务端和客户端     本文地址:https:// ...

  6. C#TCP通讯框架

    开源的C#TCP通讯框架 原来收费的TCP通讯框架开源了,这是一款国外的开源TCP通信框架,使用了一段时间,感觉不错,介绍给大家 框架名称是networkcomms 作者开发了5年多,目前已经停止开发 ...

  7. 推荐一款开源的C#TCP通讯框架

    原来收费的TCP通讯框架开源了,这是一款国外的开源TCP通信框架,使用了一段时间,感觉不错,介绍给大家 框架名称是networkcomms 作者开发了5年多,目前已经停止开发,对于中小型的应用场景,够 ...

  8. java基础55 UDP通讯协议和TCP通讯协议

    本文知识点(目录): 1.概述    2.UDP通讯协议    3.TCPP通讯协议 1.概述 1.在java中网络通讯作为Socket(插座)通讯,要求两台都必须安装socket.    2.不同的 ...

  9. Matlab中TCP通讯-实现外部程序提供优化目标函数解

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Matlab中TCP通讯-实现外部程序提供优化目标函数解     本文地址:http://te ...

随机推荐

  1. AngularJs中,如何在父元素中调用子元素为自定义Directive中定义的函数?

    最近一段时间准备使用AngularJs中的自定义Directive重构一下代码. 在这里说明一下,把自定义控件封装成Directive并不一定是要复用,而是要让代码结构更加清晰.就好像你将一个长方法拆 ...

  2. magento表单的导出

    1.Grid.php中得有:   $this->addExportType('*/*/exportXml' , Mage::helper('hpusernetwork' )->__('Ex ...

  3. netty初探(2)

    上一篇 netty(1) 一.TCP/IP 流式传输 在上文演示了2进制流式传输引起的TCP拆包问题,这里继续演示文本型的传输问题,文本型的可以有以下几种策略 1.1 以特殊字符表示结尾 HTTP协议 ...

  4. Java基本知识

    一.I/O 分字节流和字符流 字节流由InputStream和OutputStream读入和写入 DataInputStream继承自FilterInputStream,可以读取基本数据类型(char ...

  5. transient关键字小结

    java中实现序列化有两种实现方式,一种是自动的,只要实现Serilizable接口,另一种是需要手动指定需要序列化的成员变量,实现Externalizable接口. transient的特点: 1. ...

  6. sqlite导入后无法使用

    问题:sqlite导入后无法使用 解决方式:引入sqlite3 的libraries ,然后再在 projectName-Bridging-Header.h 中添加 #import "sql ...

  7. TOMcat9 免安装版的配置

    在这里默认大家都安装了jdk并且配置了java的环境,网上教程很多. 在tomcat官网(http://tomcat.apache.org/download-90.cgi)上下载和自己系统匹配的安装包 ...

  8. how to make a git repo un-git?

    If you have a git repo and now you want to make it a plain filesystem tree .. (removing the git trac ...

  9. bigdata之hadoop and spark

    目前正在学习Hadoop和spark之类的东西,一个月把Hadoop的基础东西过了一遍,但是感觉好动都没跟上老师的课程,哪位前辈了解这方面的东西希望给指点迷津.接下来我们还要学习spark和nosql ...

  10. winform窗体对象 单例模式与泛型结合

    实现弹出窗体对象的单例模式  结合泛型后,可以用于所有窗体的弹出操作 public class BaseFrm<T> where T : Form, new() { //定义一个静态的,私 ...