QTcpServer QTcpScoket通讯

最近需要一个数据转发的程序,昨天快下班之前看了QTcpServer和QTcpSocket模块,边看文档,边写了一个发送消息的demo。下完就下班了,今天早晨来测试,发现没什么问题。
QTcpServer 和QtcpSocket的封装,让我们写这类程序变得非常的简单了。

  1. 实例化一个QTcpServer对象,启动监听程序来监听某个端口。
  2. 有连接过来后,建立连接,然后通过这个链接进行通讯
    因为QTcpSocket继承自QIOdevice 所以可以通过流的方式来操作,可以进行读写。

好了,先看看我写的demo的服务端
界面是随便的拖了一个按钮,堆起来的。
服务端界面

.h文件代码
#ifndef TCPSERVICETESTDLG_H
#define TCPSERVICETESTDLG_H

#include <QDialog>
#include <QMap>

class QTcpServer;
class QTcpSocket;

namespace Ui {
class TCPServiceTestDlg;
}

class TCPServiceTestDlg : public QDialog
{
    Q_OBJECT
public:
    explicit TCPServiceTestDlg(QWidget *parent = 0);
    ~TCPServiceTestDlg();
private:
    void handleSendData(QTcpSocket * socket,const QString& msg); //处理发送数据
private slots:
    void on_tb_start_clicked();//开始监听
    //停止监听
    void on_tb_stop_clicked();
    //发送数据
    void on_pb_send_clicked();
protected slots:
    void slot_handleNewConnection();//处理连接
    void slot_handleReciveData(); //接收数据
    void slot_handleDisconnectSocket();//处理断开连接
private:
    Ui::TCPServiceTestDlg *ui;
    QTcpServer * server;
    QMap<QString,QTcpSocket *> socketMap; //记录链接进来的ip
};

#endif // TCPSERVICETESTDLG_H


.cpp代码
#include "TCPServiceTestDlg.h"
#include "ui_TCPServiceTestDlg.h"
#include <QTcpServer>
#include <QTcpSocket>
#include <QDateTime>

TCPServiceTestDlg::TCPServiceTestDlg(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TCPServiceTestDlg)
{
    ui->setupUi(this);
    server = new QTcpServer(this);
    connect(server,&QTcpServer::newConnection,this,&TCPServiceTestDlg::slot_handleNewConnection);
    this->ui->tb_stop->setEnabled(false);
}

TCPServiceTestDlg::~TCPServiceTestDlg()
{
    delete ui;
}

void TCPServiceTestDlg::handleSendData(QTcpSocket *socket, const QString &msg)
{
    if(socket->isOpen())
    {
        QString sMsg = "发送:" + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + msg;
        QByteArray ba = sMsg.toUtf8();//用UTF8编码,要求服务端和客户端要用一样的编码,这样才能保证不会乱码
        socket->write(ba);

    }
}

void TCPServiceTestDlg::on_tb_start_clicked()
{

    int prot = this->ui->sb_Port->value();
    if(!server->listen(QHostAddress::Any,prot))
    {
        qDebug()<<server->errorString();
        this->ui->tb_stop->setEnabled(false);
    }
    else
    {
        this->setWindowTitle("start success");
        this->ui->tb_start->setEnabled(false);
        this->ui->tb_stop->setEnabled(true);
    }

}

void TCPServiceTestDlg::on_tb_stop_clicked()
{
    if(server->isListening())
    {
        server->close();
        this->ui->tb_start->setEnabled(true);
        this->ui->tb_stop->setEnabled(false);
    }
}

void TCPServiceTestDlg::slot_handleNewConnection()
{
    QTcpSocket * socket = server->nextPendingConnection();
    QString ipStr = socket->peerAddress().toString();
    this->ui->lw_ip->addItem(ipStr);
    socketMap.insert(ipStr,socket);
    connect(socket,&QTcpSocket::disconnected,this,&TCPServiceTestDlg::slot_handleDisconnectSocket);
    connect(socket,&QTcpSocket::readyRead,this,&TCPServiceTestDlg::slot_handleReciveData);
}


void TCPServiceTestDlg::slot_handleReciveData()
{
    QTcpSocket * socket = dynamic_cast<QTcpSocket*>(sender());
    if(socket!=NULL)
    {
         QString ipStr = socket->peerAddress().toString();
         while(socket->bytesAvailable())
         {
             QByteArray vTemp=socket->readAll();
             QString msg = ipStr + ":" + QString::fromUtf8(vTemp);
             this->ui->te_reciveContent->append(msg);
         }
    }
}

/**
 * @brief TCPServiceTestDlg::slot_handleDisconnectSocket
 * 处理断开连接时的操作,断开连接时。把ip列表中断开的socket移除
 * 同时把保存下来的socketMap中的socket移除,然后销毁socket
 */
void TCPServiceTestDlg::slot_handleDisconnectSocket()
{
    QTcpSocket * socket = dynamic_cast<QTcpSocket*>(sender());
    if(socket!=NULL)
    {
        QString ipStr = socket->peerAddress().toString();
        if(socketMap.keys().contains(ipStr))
        {
            QList<QListWidgetItem*> items = this->ui->lw_ip->findItems(ipStr,Qt::MatchExactly);

            foreach(QListWidgetItem *item , items)
            {
                this->ui->lw_ip->removeItemWidget(item);//remove后必须delete掉,不然界面上无法删除
                delete item;
            }
            socketMap.remove(ipStr);
        }
    }
    socket->deleteLater();
}


/**
 * @brief TCPServiceTestDlg::on_pb_send_clicked
 * 选定需要发送数据的ip,然后发送内容
 */
void TCPServiceTestDlg::on_pb_send_clicked()
{
    QString text = this->ui->le_sendContent->text();
    QList<QListWidgetItem*> items = this->ui->lw_ip->selectedItems();
    foreach(QListWidgetItem * item ,items)
    {
        QTcpSocket * socket = socketMap.value(item->text());
        if(socket!=NULL)
        {
            handleSendData(socket,text);
        }
    }

    this->ui->le_sendContent->clear();
}
Pro文件代码
#-------------------------------------------------
#
# Project created by QtCreator 2015-04-08T16:20:07
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = ZTCPTEST
TEMPLATE = app


SOURCES += main.cpp\
        TCPServiceTestDlg.cpp

HEADERS  += TCPServiceTestDlg.h

FORMS    += TCPServiceTestDlg.ui

客户端界面:
客户端界面

.h文件
#ifndef TCPCLIENTTESTDLG_H
#define TCPCLIENTTESTDLG_H

#include <QDialog>
class QTcpSocket;
namespace Ui {
class TCPClientTestDlg;
}

class TCPClientTestDlg : public QDialog
{
    Q_OBJECT

public:
    explicit TCPClientTestDlg(QWidget *parent = 0);
    ~TCPClientTestDlg();
public:
    void handleSendData(QTcpSocket *socket, const QString &msg);
private slots:
    void on_pBtnSend_clicked();

    void on_pBtnConnect_clicked();

    void on_pBtnDisconnect_clicked();

protected slots:
    void slot_handleReciveData();


private:
    Ui::TCPClientTestDlg *ui;
    QTcpSocket * socket;
};

#endif // TCPCLIENTTESTDLG_H


.cpp文件
#include "TCPClientTestDlg.h"
#include "ui_TCPClientTestDlg.h"

#include <QTcpSocket>
#include <QHostAddress>
#include <QDateTime>
#include <QDebug>

TCPClientTestDlg::TCPClientTestDlg(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TCPClientTestDlg)
{
    ui->setupUi(this);
    socket = new QTcpSocket(this);

    connect(socket,&QTcpSocket::readyRead,this,&TCPClientTestDlg::slot_handleReciveData);
     this->ui->pBtnDisconnect->setEnabled(true);
}

void TCPClientTestDlg::handleSendData(QTcpSocket *socket, const QString &msg)
{
    if(socket->isOpen())
    {
        QString sMsg = "发送:" + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + msg;
        QByteArray ba = sMsg.toUtf8();
        socket->write(ba);
    }
}



TCPClientTestDlg::~TCPClientTestDlg()
{
    delete ui;
}

void TCPClientTestDlg::on_pBtnSend_clicked()
{
    if(socket->isOpen())
    {
        QString text = this->ui->le_sendTest->text();
        handleSendData(socket,text);
    }
}

void TCPClientTestDlg::slot_handleReciveData()
{
    while(socket->bytesAvailable())
    {
        QByteArray vTemp=socket->readAll();
        QString msg = QString::fromUtf8(vTemp);
        qDebug()<<msg;
    }
}

void TCPClientTestDlg::on_pBtnConnect_clicked()
{
    QString ip = this->ui->lineEdit->text();
    int port = this->ui->spinBox->value();

    QHostAddress address(ip);

    socket->connectToHost(address,port);
    this->ui->pBtnConnect->setEnabled(false);
    this->ui->pBtnDisconnect->setEnabled(true);
}

void TCPClientTestDlg::on_pBtnDisconnect_clicked()
{
   socket->disconnectFromHost();
   this->ui->pBtnConnect->setEnabled(true);
   this->ui->pBtnDisconnect->setEnabled(false);
}


Pro文件
#-------------------------------------------------
#
# Project created by QtCreator 2015-04-08T17:30:54
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = ZTCPClientTest
TEMPLATE = app


SOURCES += main.cpp\
        TCPClientTestDlg.cpp

HEADERS  += TCPClientTestDlg.h

FORMS    += TCPClientTestDlg.ui

花了一点时间来写这个,内容比较粗糙,很多问题可能没有遇到和考虑到,以后需要详细的需求在增加。
运行效果界面:
1. 服务端启动监听
2. 客户端填写服务端ip地址,建立连接
3. 发送消息
客户端运行效果
服务端运行效果

猜你喜欢

转载自blog.csdn.net/zpbrook/article/details/44956941