QT开发之旅二TCP调试工具

本文介绍了一款使用QT重写的TCP调试工具,它提供了ASCII格式和16进制数据收发功能,支持多个客户端同时进行消息交换。工具通过QTcpServer和QTcpSocket类实现,能动态增加和移除已连接客户端,并在客户端断开时自动识别。项目在WIN7环境下使用QT4.7和QT CREATOR2.8开发,源码及可执行文件提供下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.youkuaiyun.com/detail/feiyangqingyun/6717009

源码猛点这里:http://download.youkuaiyun.com/detail/feiyangqingyun/6717017

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值