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版 ...
随机推荐
- JavaBean递归拷贝工具类Dozer
JavaBean深度拷贝利器——Dozer DozerBeanMapper对象之间相同属性名赋值 DozerBeanMapper + 对象转Map方法 Dozer(JavaBean的映射工具)开发手册
- par函数mgp 参数-控制坐标轴的位置
mgp 参数的值为长度为3的一个向量,默认值为 c(3, 1, 0); 3个数值控制的元素不同 1) 第一个数值:3, 控制xlab 和 ylab的位置 示例用法: par(mfrow = c(1, ...
- jquery 实现 Json 的一些转换方法
有一个json 字符串 1)要判断该字符串是否是 json 格式 方法:将其转换成json对象,如果报异常,则不是,否则就是json格式 function isJsonFormat(str) { tr ...
- MAC 查看端口占用
命令 lsof -i tcp:[port] (port替换成端口号,比如6379)可以查看该端口被什么程序占用,并显示PID,方便KILL 之后,kill -9 [PID] , kill进程即可 ...
- Xcode 文档注释
首先要下载一个服务:[下载地址]这是一个老外写的工作流,解压缩,然后双击,安装一下, 选择xcode —> services —> services perference 安装完就会在右边 ...
- JSTL时间格式化项目小试
我在之前的博客中虽然详尽的介绍了JSTL在各个载体中的用法,也介绍了它和EL的共同使用的好处,但是只是顺便提了一下JSTL的格式化. 今天在项目中遇到了一个小问题,也就想到这,马上就开始实践了一下,效 ...
- kafka学习之-集群配置及安装
1.软件版本 kafka2.10_0.9.0.0 zookeeper_3.4.6 2.集群节点 一共有3台机器. 192.168.14.100 slave-01 192.168.14.105 slav ...
- Android Studio使用技巧小记
1.Android Studio中查看genymotion模拟器中的文件的方法: Tools-->Android Device Moniter 2.快速定位开源代码某功能的实现方法 右击项目-- ...
- php解析mpp文件中的前置任务
获取层级的project任务 参考 启动javabridge java -jar JavaBridge.jar SERVLET_LOCAL:8089 1.读取mpp文件 $file_path = & ...
- windows下安装node.js
由于shopnc的im需要node.js 先安装下node.js 下载node.js 直接运行 安装完成后 win+R,出入cmd 安装时已经自动配置了环境变量(如果没设置环境变量,变量名:NODE_ ...