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调试工具的更多相关文章

  1. QT开发之旅三串口设备调试工具

    这里首先说明一下,这个为什么叫串口设备调试工具而不是串口调试工具,是因为这个工具比网络上的串口调试工具多出了一些真实需要的用来调试设备的功能,首先一点就是大部分的串口调试工具收到数据都是立即返回,这样 ...

  2. QT开发之旅一DS7400主机调试工具

    接触QT三年有余,期间因为工作需要断断续续学习过,2010年开始接触,当时好像是4.7版本,现在都已经到5.2版本了,更新真快,前阵子安装了下5.2版本,还是有很多变化的,不过感觉好像编译速度慢了很多 ...

  3. QT开发之旅四邮件发送工具

    终于有了一个晚上安静的写写程序,最近一直忙着公司商务上的事情,一直想用QT实现一个调用最底层socket通信来实现的邮件发送程序,以前用C#写过,微软都封装好的,不知道底层是如何实现的,只知道调用方法 ...

  4. QT开发(十二)——QT事件处理机制

    一.QT事件简介 QT程序是事件驱动的, 程序的每个动作都是由内部某个事件所触发.QT事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. 常见的QT事件类型如下: 键盘事件: 按键按下和松开 ...

  5. QT开发之旅-Udp聊天室编程

    一.概要设计 登录对话框(继承自QDialog类)进行用户登录查询数据库用户是否存在,注册插入数据到用户表.用户表字段: (chatid int primary key, passwd varchar ...

  6. Matlab+Qt开发笔记(二):Qt打开mat文件显示读取的数据

    前言   介绍了基础环境,最终是为了读取显示.mat文件,本篇读取mat文件并显示.   补充   测试的mat文件是double类型的. Matlab库数据类型 变量类型:matError,错误变量 ...

  7. C#微信开发之旅(二):基础类之HttpClientHelper(更新:SSL安全策略)

    public class HttpClientHelper   2     {   3         /// <summary>   4         /// get请求   5    ...

  8. VS2008下QT开发环境搭建(转)

    原博文地址:http://blog.csdn.net/sunnyboycao/article/details/6364444 VS2008集成QT4.7.2环境搭建 作者:jimmy 日期:2011- ...

  9. Matlab+Qt开发笔记(一):matlab搭建Qt开发matlib环境以及Demo测试

    前言   做一些数据处理软件,使用matlab文件,.mat文件.   准备条件   安装matlab2016,发现是vs 12(是vs2011版本),Qt5.9.3是支持vs 14(是vs2015版 ...

随机推荐

  1. Lambda动态排序

    private static IList<T> IListOrderBy<T>(IList<T> list, string propertyName) where ...

  2. 如何在集群中获得处理本次请求的web容器的端口号?

    系统四台机器,每台机器部署四个Tomcat Web容器.现需要根据端口号随机切换到映射的数据源,若一台机器一个Tomcat则用IP识别,可现在一台机器四个Tomcat,因此还需要获得Web容器的端口号 ...

  3. VMware克隆虚拟机后无法启动网卡

    最简单的办法: 修改这个文件:/etc/udev/rules.d/70_persistent-net.rules 把eth1修改为eth0,记下里面的mac地址 修改/etc/sysconfig/ne ...

  4. Python爬虫学习——获取网页

    通过GET请求获取返回的网页,其中加入了User-agent信息,不然会抛出"HTTP Error 403: Forbidden"异常, 因为有些网站为了防止这种没有User-ag ...

  5. [转帖]CentOS下iRedMail安装配置

    CentOS下iRedMail安装配置 中文名为艾瑞得邮件,由 rhms 项目更名而来.是针对 Linux 设计的邮件服务器解决方案,是在操作系统安装好后使用的一套 shell 脚本,用于快速部署一套 ...

  6. 解决ESXi有虚拟机模版部署的CentOS虚拟机,网卡eth0找不到问题

    1,问题和虚拟机克隆后出现网卡找不到问题类似. 2,修改主机名hostname 修改 /etc/sysconfig/network文件 3,删除/etc/sysconfig/network-scrip ...

  7. 常用Dos(转)

    先介绍一下通配符的概念. 通配符*和? *表示一个字符串 ?只代表一个字符 注意通配符只能通配文件名或扩展名,不能全都表示.例如我们要查找以字母y开头的所有文件,可以输入以下命令:dir y*.*:如 ...

  8. zookeeper入门系列讲解

    zookeeper可谓是目前使用最广泛的分布式组件了.其功能和职责单一,但却非常重要.    在现今这个年代,介绍zookeeper的书和文章可谓多如牛毛,本人不才,试图通过自己的理解来介绍zooke ...

  9. Nginx 向客户端输出真实的后端IP地址

    因为涉及到内外网的改造,所以狠多东西现在需要依赖于openresty来做总控实现.然后就碰见了一个比较难办的问题,即在upstream时候,如何获取实际处理请求的server地址.假设有如下upstr ...

  10. zabbix服务端安装指南及常见问题解决

    1. 首先要准备LNMP环境 2. 在mysql中创建zabbix所需要的库和用户 mysql -uroot -pmysql> CREATE DATABASE zabbix CHARACTER ...