QT开发之旅二TCP调试工具
TCP调试工具顾名思义用来调试TCP通信的,网上这样的工具N多,之前用.NET写过一个,无奈在XP下还要安装个.NET框架才能运行,索性这次用QT重写,发现QT写TCP通信比.NET还要便捷一些,运行效率貌似要高,还能识别客户端断开,这个真神奇,除了断电之外。
项目名称:TCP调试工具
开发环境:WIN7+QT4.7+QT CREATOR2.8+MINGW
技术实现:通过QTcpServer和QTcpSocket类,解析协议并作出处理
实现功能:ASCII格式和16进制数据收发,支持多个客户端收发消息,可以指定客户端发送消息,动态增加和移除已连接客户端。
运行截图:
粗略步骤:
第一步:添加主界面,布局好主界面,并命名好控件,例如服务端的清空按钮命名为btnClearServer,客户端的清空按钮命名为btnClearClient。
第二步:编写服务端中客户端通信类,服务端可以接受多个客户端的连接,这里采用了同步通信机制,先编写myTcpClient类,封装了客户端连接断开接收数据的操作。具体代码如下:
myTcpClient.h #ifndef MYTCPCLIENT_H #define MYTCPCLIENT_H #include <QTcpSocket> class myTcpClient : public QTcpSocket { Q_OBJECT public: explicit myTcpClient(QObject *parent = 0,int clientID=0); private: int clientID; signals: void ClientReadData(int clientID,QString IP,int Port,QByteArray data); void ClientDisConnect(int clientID,QString IP,int Port); private slots: void ReadData(); void DisConnect(); public slots: }; #endif // MYTCPCLIENT_H myTcpClient.cpp #include "mytcpclient.h" #include <QHostAddress> #include "myhelper.h" myTcpClient::myTcpClient(QObject *parent,int clientID) : QTcpSocket(parent) { this->clientID=clientID; connect(this,SIGNAL(readyRead()),this,SLOT(ReadData()));//挂接读取数据信号 connect(this,SIGNAL(disconnected()),this,SLOT(DisConnect()));//关闭连接时,发送断开连接信号 //如果关闭连接自动删除,则下次不能再次监听,奇怪的问题 //connect(this,SIGNAL(disconnected()),this,SLOT(deleteLater()));//关闭连接时,对象自动删除 } void myTcpClient::ReadData() { myHelper::Sleep(100); //读取完整一条数据并发送信号 QByteArray data=this->readAll(); emit ClientReadData(this->clientID,this->peerAddress().toString(),this->peerPort(),data); } void myTcpClient::DisConnect() { //断开连接时,发送断开信号 emit ClientDisConnect(this->clientID,this->peerAddress().toString(),this->peerPort()); }
一旦客户端断开则发送ClientDisConnect信号,参数包含IP地址和端口。
第三步:编写服务端通信类。
myTcpServer.h #ifndef MYTCPSERVER_H #define MYTCPSERVER_H #include <QTcpServer> #include "mytcpclient.h" class myTcpServer : public QTcpServer { Q_OBJECT public: explicit myTcpServer(QObject *parent = 0); void SendData(int clientID, QByteArray data); void SendDataCurrent(QByteArray data); void SendDataAll(QByteArray data); int ClientCount()const{return clientCount;} void CloseAllClient(); private: QList<myTcpClient *> ClientList; QList<int> ClientID; myTcpClient *CurrentClient; int clientCount; protected: void incomingConnection(int handle); signals: void ClientReadData(int clientID,QString IP,int Port,QByteArray data); void ClientConnect(int clientID,QString IP,int Port); void ClientDisConnect(int clientID,QString IP,int Port); private slots: void DisConnect(int clientID,QString IP,int Port); public slots: }; #endif // MYTCPSERVER_H myTcpServer.cpp #include "mytcpserver.h" #include <QHostAddress> myTcpServer::myTcpServer(QObject *parent) : QTcpServer(parent) { this->clientCount=0; } void myTcpServer::incomingConnection(int handle) { myTcpClient *client=new myTcpClient(this,handle); client->setSocketDescriptor(handle); connect(client,SIGNAL(ClientReadData(int,QString,int,QByteArray)),this,SIGNAL(ClientReadData(int,QString,int,QByteArray))); connect(client,SIGNAL(ClientDisConnect(int,QString,int)),this,SLOT(DisConnect(int,QString,int))); emit ClientConnect(handle, client->peerAddress().toString(),client->peerPort()); ClientList.append(client);//将新的连接添加到客户端列表 ClientID.append(handle);//将新的连接的ID添加到客户端ID列表 clientCount++; //存储当前连接 CurrentClient=client; } void myTcpServer::DisConnect(int clientID,QString IP,int Port) { for (int i=0;i<clientCount;i++) { if (ClientID[i]==clientID) { ClientList.removeAt(i);//从列表中移除该连接 ClientID.removeAt(i); clientCount--; i--;//不然的话,永远只会移除第一个连接 emit ClientDisConnect(clientID,IP,Port); break; } } } //指定客户端连接发消息 void myTcpServer::SendData(int clientID, QByteArray data) { for (int i=0;i<clientCount;i++) { if (ClientID[i]==clientID) { ClientList[i]->write(data); break; } } } //对当前连接发送数据 void myTcpServer::SendDataCurrent(QByteArray data) { //如果没有一个存在的连接,则不处理 if (clientCount<1){return;} CurrentClient->write(data); } //对所有连接发送数据 void myTcpServer::SendDataAll(QByteArray data) { for (int i=0;i<clientCount;i++) { ClientList[i]->write(data); } } void myTcpServer::CloseAllClient() { for (int i=0;i<clientCount;i++) { ClientList[i]->close(); i--;//不然的话,永远只会断开第一个连接 } }
这里封装了指定客户端发消息,对当前连接发消息,对所有客户端发消息三种发送消息方法。
最开始的时候发现直接close停止监听,发现依然可以接收客户端的消息,原因是还没有关闭客户端连接,所以增加了CloseAllClient()方法,用来关闭所有客户端连接,这样的话才是彻底的停止监听。
可执行文件下载地址:http://download.csdn.net/detail/feiyangqingyun/6717009
源码猛点这里:http://download.csdn.net/detail/feiyangqingyun/6717017
QT开发之旅二TCP调试工具的更多相关文章
- QT开发之旅三串口设备调试工具
这里首先说明一下,这个为什么叫串口设备调试工具而不是串口调试工具,是因为这个工具比网络上的串口调试工具多出了一些真实需要的用来调试设备的功能,首先一点就是大部分的串口调试工具收到数据都是立即返回,这样 ...
- QT开发之旅一DS7400主机调试工具
接触QT三年有余,期间因为工作需要断断续续学习过,2010年开始接触,当时好像是4.7版本,现在都已经到5.2版本了,更新真快,前阵子安装了下5.2版本,还是有很多变化的,不过感觉好像编译速度慢了很多 ...
- QT开发之旅四邮件发送工具
终于有了一个晚上安静的写写程序,最近一直忙着公司商务上的事情,一直想用QT实现一个调用最底层socket通信来实现的邮件发送程序,以前用C#写过,微软都封装好的,不知道底层是如何实现的,只知道调用方法 ...
- QT开发(十二)——QT事件处理机制
一.QT事件简介 QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发.QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. 常见的QT事件类型如下: 键盘事件: 按键按下和松开 ...
- QT开发之旅-Udp聊天室编程
一.概要设计 登录对话框(继承自QDialog类)进行用户登录查询数据库用户是否存在,注册插入数据到用户表.用户表字段: (chatid int primary key, passwd varchar ...
- Matlab+Qt开发笔记(二):Qt打开mat文件显示读取的数据
前言 介绍了基础环境,最终是为了读取显示.mat文件,本篇读取mat文件并显示. 补充 测试的mat文件是double类型的. Matlab库数据类型 变量类型:matError,错误变量 ...
- C#微信开发之旅(二):基础类之HttpClientHelper(更新:SSL安全策略)
public class HttpClientHelper 2 { 3 /// <summary> 4 /// get请求 5 ...
- VS2008下QT开发环境搭建(转)
原博文地址:http://blog.csdn.net/sunnyboycao/article/details/6364444 VS2008集成QT4.7.2环境搭建 作者:jimmy 日期:2011- ...
- Matlab+Qt开发笔记(一):matlab搭建Qt开发matlib环境以及Demo测试
前言 做一些数据处理软件,使用matlab文件,.mat文件. 准备条件 安装matlab2016,发现是vs 12(是vs2011版本),Qt5.9.3是支持vs 14(是vs2015版 ...
随机推荐
- Oracle数据库order by排序查询分页比不分页还慢问题解决办法
简单说下问题,有一个JDBC的查询SQL,分页查询语句中有一个排序order by create_time,理论上来说JDBC查询已经是比较底层的技术了,没有像Hibernate.MyBatis那样又 ...
- AOP (面向切面编程)
AOP (面向切面编程) 留个参考的地址,还没看呢:http://www.cnblogs.com/zhaolb/p/4875167.html
- java.lang.IllegalArgumentException: Request header is too large 解决方案
错误描述: java.lang.IllegalArgumentException: Request header is too large 问题分析: 请求头超过了tomcat的限值.本来post请求 ...
- linux中crontab命令
一.crond简介 crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动cro ...
- win7下命令行提示符从C盘进入E盘的文件夹下
进入E:\papercode\3D-point-cloud-generation-master\3D-point-cloud-generation-master
- 以Windows服务方式启动MySQL,并将其默认编码设置为UTF-8
系统环境:Windows XP Professional 版本 2002 Service Pack 3 // 第1步:创建选项文件.首先下载mysql-5.5.12-win32.zip,只需复制mys ...
- 支持Android 的几款开源3D引擎调研
最近由于工作需要,对支持Android的一些开源3D引擎做了调研,结果如下: 1.Ogre 十分强大的一款3D引擎,号称工业级标准的开源项目,不仅可以用于游戏,还可以用于其他和3D相关的软件.大多数该 ...
- 基于Java对图片进行二值化处理
一直以来对Java的图形处理能力表无力,但好像又不是那么一回事,之前用PHP做过一些应用,涉及到验证码的识别,其中有个图片二值化的步骤,今天换成Java来实现下 在java的扩展包javax.imag ...
- 在IE和Firefox中实现Flash透明背景
要在一个静态的背景上加一个透明的Flash会显示动态的效果,按照常规方式加了代码后,在IE中能显示透明背景Flash,但是用Firefox浏览器却发现没有透明的效果,那究竟应该怎么加呢?于是搜索和研究 ...
- 非抢占式RCU实现(二),解释:为什么 RCU_NEXT_SIZE 宏值是4?
参考:2.6.34 一个很奇怪的问题. 没有查找到为什么 RCU_NEXT_SIZE的值为4的原因(包括Documentation),主要是在rcu_state中定义了一个四级的list,感到很有意思 ...