基于QTcpSocket和QTcpServer的Tcp通讯以及QDataStream序列化数据
2015-06-12 16:51
741 查看
最近要在QT下开发Tcp通讯,发送序列化数据以便于接收。
这里涉及到几个问题:
1.QTcpSocket、QTcpServer的通讯
2.QDataStream序列化数据
多的不说,直接上干货!!!
客户端:
tcpclient.h
tcpclient.cpp
服务器端:
tcpserver.h
tcpserver.cpp
server.h
server.cpp
在这里要特别说明一下,在此遇到的几个问题,希望能帮到大家,也提醒一下自己。
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.重载的时候一定要正确。
这里涉及到几个问题:
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 = 0); ~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 = 0; int accele_speed =0; int p_some = 0; 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 = "8080"; 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 = 8 + dataLength; control_Motor.data = stringData; QString data = stringMotor+stringData; m_motor = new Motor(20,40,60); //Motor m_motor(20,40,60); //用于暂存要发送的数据 QByteArray block; //使用数据流写入数据 QDataStream out(&block,QIODevice::WriteOnly); //设置数据流的版本,客户端和服务器端使用的版本要相同 out.setVersion(QDataStream::Qt_4_6); out<<(quint32) 0; //设置发送长度初始值为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(0); //重置字节流长度 //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(0); 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 = 0); ~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 = 8080; 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 = 0;} 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=0,int port=0); 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=0;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=0;i<TcpClientSocketList.count();i++) if (TcpClientSocketList.at(i)->socketDescriptor()==socketDescriptor) { TcpClientSocketList.removeAt(i); return; } } void Server::dataReceive() { qDebug()<<"QQWQW11111111111111"; //quint32 size = 0; quint32 nextBlockSize = 0; qDebug()<<"TcpClientSocketList.count()"<<TcpClientSocketList.count(); //for(int i = 0; i < TcpClientSocketList.count();i++) //{ QDataStream in(tcpClientSocket); in.setVersion(QDataStream::Qt_4_6); if(nextBlockSize == 0) { 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.重载的时候一定要正确。
相关文章推荐
- 手动设置Xen Host网络
- HTTPS原理
- HttpModule的认识与深入理解及MVC运行机制
- 简约之美Jodd-http--应用一箩筐
- XUtils源码分析之HttpUtils(一)
- java执行http请求乱码解决
- udp tcp
- Android 中 HttpClient作客户端,Tomcat Servlet作服务器的交互示例
- 做一个程序来查询手机号码的归属地(使用的是HttpURLConnection的post提交方式)
- Http协议与TCP协议简单理解
- Linux centos 连接网络
- 【Floyd】BZOJ1491: [NOI2007]社交网络
- Fat-tree 胖树交换网络
- 我们常常会从网络获取数据,而数据通常又为JSON格式,JSON数据转为Model对象
- HTTP常见状态码
- linux 下网络流量监控
- 无线路由器桥接、中继、电力猫组网方法分享
- 网络编程基础:1
- Java课程实验报告 实验四 Java网络编程及安全
- 本地连接和无线网络连接控制