Qt实现简单的TCP通信

这段时间用到了QT的TCP通信,做了初步的学习与尝试,编写了一个客户端和服务器基于窗口通信的小例程。

使用QT的网络套接字需要.pro文件中加入一句:

QT += network

一、客户端

1、客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:

(1)创建QTcpSocket套接字对象

socket = new QTcpSocket();

(2)使用这个对象连接服务器

socket->connectToHost(IP, port);

(3)使用write函数向服务器发送数据

socket->write(data);

(4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据

QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);  void MainWindow::socket_Read_Data()  {      QByteArray buffer;      //读取缓冲区数据      buffer = socket->readAll();  }

(5)断开与服务器的连接(关于close()和disconnectFromHost()的区别,可以按F1看帮助)

socket->disconnectFromHost();

2、以下是客户端的例程

首先是mainwindow.h文件:

 //mainwindow.h  #ifndef MAINWINDOW_H  #define MAINWINDOW_H  #include <QMainWindow>  #include <QTcpSocket>  namespace Ui {  class MainWindow;  }  class MainWindow : public QMainWindow  {      Q_OBJECT  public:      explicit MainWindow(QWidget *parent = 0);      ~MainWindow();  private slots:      void on_pushButton_Connect_clicked();      void on_pushButton_Send_clicked();      void socket_Read_Data();      void socket_Disconnected();  private:      Ui::MainWindow *ui;      QTcpSocket *socket;  }; #endif // MAINWINDOW_H

然后是mainwindow.cpp文件:

//mainwindow.cpp  #include "mainwindow.h"  #include "ui_mainwindow.h"  MainWindow::MainWindow(QWidget *parent) :      QMainWindow(parent),      ui(new Ui::MainWindow)  {      ui->setupUi(this);      socket = new QTcpSocket();      //连接信号槽      QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);      QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);      ui->pushButton_Send->setEnabled(false);      ui->lineEdit_IP->setText("127.0.0.1");      ui->lineEdit_Port->setText("8765");  }  MainWindow::~MainWindow()  {      delete this->socket;      delete ui;  }  void MainWindow::on_pushButton_Connect_clicked()  {      if(ui->pushButton_Connect->text() == tr("连接"))      {          QString IP;          int port;          //获取IP地址          IP = ui->lineEdit_IP->text();          //获取端口号          port = ui->lineEdit_Port->text().toInt();          //取消已有的连接          socket->abort();          //连接服务器          socket->connectToHost(IP, port);          //等待连接成功          if(!socket->waitForConnected(30000))          {              qDebug() << "Connection failed!";              return;          }          qDebug() << "Connect successfully!";          //发送按键使能          ui->pushButton_Send->setEnabled(true);          //修改按键文字          ui->pushButton_Connect->setText("断开连接");      }      else      {          //断开连接          socket->disconnectFromHost();          //修改按键文字          ui->pushButton_Connect->setText("连接");          ui->pushButton_Send->setEnabled(false);      }  }  void MainWindow::on_pushButton_Send_clicked()  {      qDebug() << "Send: " << ui->textEdit_Send->toPlainText();       //获取文本框内容并以ASCII码形式发送      socket->write(ui->textEdit_Send->toPlainText().toLatin1());      socket->flush();  }  void MainWindow::socket_Read_Data()  {      QByteArray buffer;      //读取缓冲区数据      buffer = socket->readAll();      if(!buffer.isEmpty())      {          QString str = ui->textEdit_Recv->toPlainText();          str+=tr(buffer);          //刷新显示          ui->textEdit_Recv->setText(str);      }  }  void MainWindow::socket_Disconnected()  {      //发送按键失能      ui->pushButton_Send->setEnabled(false);      //修改按键文字      ui->pushButton_Connect->setText("连接");      qDebug() << "Disconnected!";  }

最后是ui的设计:

二、服务器

1、服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:

(1)创建QTcpSever对象

server = new QTcpServer();

(2)侦听一个端口,使得客户端可以使用这个端口访问服务器

server->listen(QHostAddress::Any, port);

(3)当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问

 connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);  void MainWindow::server_New_Connect()  {      //获取客户端连接      socket = server->nextPendingConnection();  }

(4)使用socket的write函数向客户端发送数据

socket->write(data);

(5)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据

 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);  void MainWindow::socket_Read_Data()  {      QByteArray buffer;      //读取缓冲区数据      buffer = socket->readAll();  }

(6)取消侦听

server->close();

2、以下是服务器的例程

首先是mainwindow.h文件:

//mainwindow.h  #ifndef MAINWINDOW_H  #define MAINWINDOW_H  #include <QMainWindow>  #include <QTcpServer>  #include <QTcpSocket>  namespace Ui {  class MainWindow;  }  class MainWindow : public QMainWindow  {      Q_OBJECT  public:      explicit MainWindow(QWidget *parent = 0);      ~MainWindow();  private slots:      void on_pushButton_Listen_clicked();      void on_pushButton_Send_clicked();      void server_New_Connect();      void socket_Read_Data();      void socket_Disconnected();  private:      Ui::MainWindow *ui;      QTcpServer* server;      QTcpSocket* socket;  }; #endif // MAINWINDOW_H

然后是mainwindow.cpp文件:

#include "mainwindow.h" #include "ui_mainwindow.h"  MainWindow::MainWindow(QWidget *parent) :      QMainWindow(parent),      ui(new Ui::MainWindow)  {      ui->setupUi(this);      ui->lineEdit_Port->setText("8765");      ui->pushButton_Send->setEnabled(false);      server = new QTcpServer();      //连接信号槽      connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);  }  MainWindow::~MainWindow()  {      server->close();      server->deleteLater();      delete ui;  }  void MainWindow::on_pushButton_Listen_clicked()  {      if(ui->pushButton_Listen->text() == tr("侦听"))      {          //从输入框获取端口号          int port = ui->lineEdit_Port->text().toInt();          //监听指定的端口          if(!server->listen(QHostAddress::Any, port))          {              //若出错,则输出错误信息              qDebug()<<server->errorString();              return;          }          //修改按键文字          ui->pushButton_Listen->setText("取消侦听");          qDebug()<< "Listen succeessfully!";      }      else      {  /*          //如果正在连接(点击侦听后立即取消侦听,若socket没有指定对象会有异常,应修正——2017.9.30)          if(socket->state() == QAbstractSocket::ConnectedState)          {              //关闭连接              socket->disconnectFromHost();          }  */          socket->abort();          //取消侦听          server->close();          //修改按键文字          ui->pushButton_Listen->setText("侦听");          //发送按键失能          ui->pushButton_Send->setEnabled(false);      }  }  void MainWindow::on_pushButton_Send_clicked()  {      qDebug() << "Send: " << ui->textEdit_Send->toPlainText();      //获取文本框内容并以ASCII码形式发送      socket->write(ui->textEdit_Send->toPlainText().toLatin1());      socket->flush();  }  void MainWindow::server_New_Connect()  {      //获取客户端连接      socket = server->nextPendingConnection();      //连接QTcpSocket的信号槽,以读取新数据      QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);      QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);      //发送按键使能      ui->pushButton_Send->setEnabled(true);      qDebug() << "A Client connect!";  }  void MainWindow::socket_Read_Data()  {      QByteArray buffer;      //读取缓冲区数据      buffer = socket->readAll();      if(!buffer.isEmpty())      {          QString str = ui->textEdit_Recv->toPlainText();          str+=tr(buffer);          //刷新显示          ui->textEdit_Recv->setText(str);      }  }  void MainWindow::socket_Disconnected()  {      //发送按键失能      ui->pushButton_Send->setEnabled(false);      qDebug() << "Disconnected!";  }

最后是ui的设计:

三、运行结果

推荐阅读

    电脑tcpip协议|计算机tcpip协议

    电脑tcpip协议|计算机tcpip协议,,计算机tcpip协议在互联网使用的各种协议中最重要和最著名的就是 TCP/IP 两个协议。现在人们经常提到的 T

    TCP和UDP的主要区别是什么

    TCP和UDP的主要区别是什么,数据,协议,TCP和UDP的主要区别是什么1、在连接上,TCP是基于连接的,是面向连接的运输层协议,如打电话之前要拨号建

    IP头、TCP头、UDP头详解以及定义

    IP头、TCP头、UDP头详解以及定义,报文,字节,IP数据包也叫IP报文分组,传输在ISO网络7层结构中的网络层,它由IP报文头和IP报文用户数据组成,IP

    TCP是什么意思

    TCP是什么意思,协议,数据包,数据,传输,节点,确保,TCP,即传输控制协议(Transmission Control Protocol),是一种网络通信协议,旨在通过Internet发送数

    tcp和udp有什么区别

    tcp和udp有什么区别,数据,连接,报文,传输,状态,协议,tcp和udp的区别有:1、udp是无连接的,tcp是面向连接的;2、udp是不可靠传输,tcp是可靠传输;3、udp

    Go语言TCP网络编程|详细

    Go语言TCP网络编程|详细,数据,操作, 一、序言 Golang的主要 设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端 程序必不可少

    电脑不支持tcpip|电脑不支持win11

    电脑不支持tcpip|电脑不支持win11,,电脑不支持win11由于严格的系统要求,许多计算机将无法升级到Windows 11。微软对此有自己的理由。为了检

    快车的TCP端口/UDP端口是什么

    快车的TCP端口/UDP端口是什么,端口,连接,服务进程,地址,快车,用户程序,  快车的TCP端口/UDP端口说明如下:TCP和UDP服务通常有一个用户/服务器

    tcp协议详解介绍

    tcp协议详解介绍,协议,连接,数据,应用层,实体,确认,  导读:我们在很多地方都会是否同意TCP协议的字样,很多人都不知道TCP协议到底是什么,我们为