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

最新文章

  1. [IOS]Swift 遍历预制的本地资源文件
  2. 关于js调用外部部署的web api
  3. ecshop分页
  4. 常见HTTP错误代码大全
  5. OracleHelper(对增删改查分页查询操作进行了面向对象的封装,对批量增删改操作的事务封装)
  6. 开启所有PHP错误!无论在任何时候
  7. DataTable的Merge使用
  8. Codeforces 612E - Square Root of Permutation
  9. .Net Core 系列:2、ADO.Net 基础
  10. 【HTML】DocType
  11. 记录一下html渲染页面的 js框架
  12. 【NOI2002】银河英雄传说(并查集)
  13. (面试题)python面试题集锦-附答案
  14. 【PMP】关键路径法与关键链法
  15. jstack生成的Thread Dump日志线程 分析
  16. 安装好ubuntu双系统启动时卡死解决办法
  17. 修改input的text 通过jquery的html获取值 未变化
  18. System.IO.Path文件路径类
  19. 使用just-api 进行接口测试
  20. Python学习笔记三:数据类型

热门文章

  1. ibatis中的安全问题
  2. win 10中打开sql server配置管理器
  3. 绚丽而实用的jQuery/CSS3应用及源码
  4. 多线程---再次认识volatile,Synchronize,lock
  5. gtest运行小析
  6. [转]调试AngularJS应用
  7. [Learn AF3]第六章 App Framework 3.0中的内置矢量图标
  8. ch3:文件处理与异常
  9. 如何使用 SSH 连接 VMWare 虚拟机中的 Ubuntu
  10. Kafka producer介绍