本文实例为大家分享了QT编写tcp通信工具的具体实现代码,Client篇,供大家参考,具体内容如下1.说明使用qt写一个类似网上常见的网络调试工具。此篇为Client端。下一遍再写Server端。2....

本文实例为大家分享了QT编写tcp通信工具的具体实现代码,Client篇,供大家参考,具体内容如下

1.说明

使用qt写一个类似网上常见的网络调试工具。此篇为Client端。下一遍再写Server端。

2.基本流程

Client端相对简单:创建QTcpSocket对象,为对象的readyRead,error,connected(可选)分别写槽函数,以处理读数据,错误,连接成功三个事件。

连接使用对象的connectToHost方法,断开使用disconnectFromHost方法。

程序不做编码转换处理,因为之前的几遍文字已经做过,不再赘述。

3.代码

这是mainwindow.cpp文件。

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  ui->splitter->setStretchFactor(0,2);
  ui->splitter->setStretchFactor(1,1);

  QString ip=getLocalip();
  if( ip.isEmpty() )
  {
    QMessageBox::about(this,tr("提示"),tr("无本地IP。") ) ;
  }
  else{
    ui->ledtIpLocal->setText( ip );  //本地IP
  }
  ui->labHostName->setText(tr("HostName:")+ QHostInfo::localHostName() );
  ui->labHostName->adjustSize();
  ui->ledtPortServer->setText(tr("8080")); //默认
  ui->ledtIpServer->setText (ui->ledtIpLocal->text() );
  ui->btnOpen->setEnabled(true);
  ui->btnSend->setEnabled(false);
  //初始化TCP客户端
  tcpClient = new QTcpSocket(this);
  tcpClient->abort();

  connect(tcpClient, SIGNAL(readyRead()), this, SLOT(slot_readData()) );
  connect(tcpClient, SIGNAL(connected()), this, SLOT(slot_connected()) );
  connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(slot_error(QAbstractSocket::SocketError)));
}

MainWindow::~MainWindow()
{
  delete ui;
}
//获取本地IP
QString MainWindow::getLocalip()
{
  QList<QHostAddress> list = QNetworkInterface::allAddresses();
  foreach (QHostAddress address, list)
  {
    if(address.protocol() == QAbstractSocket::IPv4Protocol)
    {
      return address.toString();
    }
  }
  return "";
}

//读取数据
void MainWindow::slot_readData()
{
  QByteArray buffer = tcpClient->readAll();
  if(!buffer.isEmpty())
  {
    ui->tedtRecive->appendPlainText( buffer );
  }
}
//连接成功,也可以在方法waitForConnected后面处理。
void MainWindow::slot_connected()
{
  ui->btnOpen->setText("断开");
  ui->btnSend->setEnabled(true);
  ui->btnOpen->setEnabled(true);
  ui->ledtPortLocal->setText( QString::number(tcpClient->localPort()) );
}
//错误处理
void MainWindow::slot_error(QAbstractSocket::SocketError)
{
  tcpClient->disconnectFromHost();
  ui->btnOpen->setText(tr("连接"));
  ui->btnOpen->setEnabled(true);
  QMessageBox::warning(this,
    tr("注意!"),
    tcpClient->errorString(),
    QMessageBox::Ok ,
    QMessageBox::Ok) ;
}
//连接与断开
void MainWindow::on_btnOpen_clicked()
{
  if(ui->btnOpen->text() == "断开")
  {
    tcpClient->disconnectFromHost();
    if (
        tcpClient->state() == QAbstractSocket::UnconnectedState \
        ||( tcpClient->waitForDisconnected(1000))
     )
    {
      ui->btnOpen->setText("连接");
      ui->btnSend->setEnabled(false);
    }
  }else{
    if( ui->ledtPortServer->text().toInt() ==0 ){
      QMessageBox::about(this,tr("提示"),tr("请输入端口号。") ) ;
      return;
    }
    tcpClient->connectToHost(ui->ledtIpServer->text(), ui->ledtPortServer->text().toInt(),QIODevice::Readwrite,QAbstractSocket::IPv4Protocol);
    ui->btnOpen->setEnabled(false);
    if( !tcpClient->waitForConnected(4000) ) //只等待4秒
    {
      tcpClient->disconnectFromHost();
      ui->btnOpen->setText(tr("连接"));
      ui->btnOpen->setEnabled(true);
      QMessageBox::warning(this,
        tr("注意!"),
        tcpClient->errorString(),
        QMessageBox::Ok ,
        QMessageBox::Ok) ;
    }
  }
}
//发送
void MainWindow::on_btnSend_clicked()
{
  if( ui->tedtSend->toPlainText().isEmpty() ){
    QMessageBox::about(this,
    tr("提示"),
    tr("请输入发送数据。")
   ) ;
   return;
  }

  tcpClient ->write( ui->tedtSend->toPlainText().toUtf8() );
}

4.附加修改

使用中发现qt文本框对回车键按“\n”处理,即使是从其他地方粘贴进来也会自动将“\r\n”转为“\n”,这有时非常不方便,比如测试wifi模块的AT命令,还有一些固定格式的网络请求。

先对界面进行修改,添加一些功能物件:

这里对发送数据进行处理:

//发送
void MainWindow::on_btnSend_clicked()
{

  if( ui->tedtSend->toPlainText().isEmpty() ){
    QMessageBox::about(this,
    tr("提示"),
    tr("请输入发送数据。")
   ) ;
   return;
  }
  QString str = ui->tedtSend->toPlainText() ;
  if( ui->checkBox2->isChecked() )
  {
    str.replace(tr("\n"),tr("\r\n"));
    str.replace(tr("\n\n"),tr("\n"));
  }
  if( ui->checkBox1->isChecked() )str.append(tr("\r\n"));
  tcpClient ->write( str.toUtf8() );
}
//计算字节数
void MainWindow::on_btnCalc_clicked()
{
  QString str = ui->tedtSend->toPlainText() ;
  int len1= str.toUtf8().length();
  if( ui->checkBox2->isChecked() )
  {
    str.replace(tr("\n"),tr("\r\n"));
    str.replace(tr("\n\n"),tr("\n"));
  }
  if( ui->checkBox1->isChecked() )str.append(tr("\r\n"));

 int len2= str.toUtf8().length();
  QMessageBox::about(this,
  tr("字节:"),
  tr("处理前:")+QString::number (len1,10)+tr(",处理后:")+ QString::number (len2,10)
 ) ;
}

为了更加方便使用,添加记忆功能,保持上次的填写的内容:

//读取ini文件对应信息
void MainWindow:: readIni(QString key, QString&value)
{
  QString path = "save.ini";
  //创建文件
  QSettings *config = new QSettings(path, QSettings::IniFormat);
  //读取信息
  QVariant variant = config->value(QString("info/") + key);
  value = variant.value<QString>();
  delete config;
}

//写入ini文件对应信息
void MainWindow::writeIni(QString key, QString value)
{
  QString path = "save.ini";
  //创建文件
  QSettings *config = new QSettings(path, QSettings::IniFormat);
  QVariant variant;
  variant.setValue(value);
  //信息写入文件
  config->beginGroup("info");
  config->setValue(key, variant);
  config->endGroup();
  delete config;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。