QT開發之旅二TCP調試工具


TCP調試工具顧名思義用來調試TCP通信的,網上這樣的工具N多,之前用.NET寫過一個,無奈在XP下還要安裝個.NET框架才能運行,索性這次用QT重寫,發現QTTCP通信比.NET還要便捷一些,運行效率貌似要高,還能識別客戶端斷開,這個真神奇,除了斷電之外。

項目名稱:TCP調試工具

開發環境:WIN7+QT4.7+QT CREATOR2.8+MINGW

技術實現:通過QTcpServerQTcpSocket類,解析協議並作出處理

實現功能: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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM