QT示例:基于TCP点对点Socket通讯

下载:基于TCP点对点通讯

一、 概述

首先介绍一下TCP:(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。相比而言UDP,就是开放式、无连接、不可靠的传输层通信协议。

二、TCP 协议工作原理

在这里插入图片描述

三、TCP 编程模型

在这里插入图片描述

四、基于TCP点对点通讯示例

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 myWidget::socket_Read_Data()
{
    QByteArray buffer;
    //读取缓冲区数据
    buffer = socket->readAll();
}

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

socket->disconnectFromHost();
socket->close();
2、客户端Client示例

.pro文件添加:

QT        +=network

myWidget.h 添加:

//#include <QtNetwork>
#include <QTcpSocket>
#include <QMessageBox>

namespace Ui {
class myWidget;
}

class myWidget : public QWidget
{
    Q_OBJECT

public:
    explicit myWidget(QWidget *parent = 0);
    ~myWidget();

private slots:
    void on_pushButton_connect_clicked(); // 连接按钮

    void socket_Read_Data();	// 数据流读取
    
    void on_pushButton_send_clicked(); // 发送数据
    
    void socket_Disconnected();	// 连接中断
private:
    Ui::myWidget *ui;
    
    QTcpSocket *socket;
    QPalette Pal0,Pal1; // 调色板
};    

myWidget.cpp 添加:

#include "mywidget.h"
#include "ui_mywidget.h"

myWidget::myWidget(QWidget *parent):QWidget(parent),ui(new Ui::myWidget)
{
    ui->setupUi(this);
    // 一、创建QTcpSocket套接字对象
    socket = new QTcpSocket;
    ui->pushButton_send->setEnabled(false);
    ui->lineEdit_IP->setText("192.168.1.100");
    ui->lineEdit_port->setText("8010");

    Pal0 =ui->pushButton_connect->palette();
    Pal1.setColor(QPalette::ButtonText,Qt::red); // 只能对按钮文本、窗口文本的动态颜色设置

    //连接信号槽
    QObject::connect(socket, &QTcpSocket::readyRead, this, &myWidget::socket_Read_Data);
    QObject::connect(socket, &QTcpSocket::disconnected, this, &myWidget::socket_Disconnected);
}

myWidget::~myWidget()
{
    delete this->socket;
    delete ui;
}

// 二、连接服务器
void myWidget::on_pushButton_connect_clicked()
{
    if(ui->pushButton_connect->text() == tr("连接"))
        {
            //获取IP地址
            QString IP = ui->lineEdit_IP->text();
            //获取端口号
            int port = ui->lineEdit_port->text().toInt();
            //取消已有的连接
            socket->abort();
            //连接服务器(使用socket对象连接服务器)
            socket->connectToHost(IP, port);
            //等待连接成功
            if(!socket->waitForConnected(30000))
            {
                QMessageBox::information(this,tr("提示"),tr("Connection failed!"),QMessageBox::Ok);
                return;
            }
            QMessageBox::information(this,tr("提示"),tr("Connect successfully!"),QMessageBox::Ok);
            // 更新界面
            ui->pushButton_send->setEnabled(true);
            ui->pushButton_connect->setText("断开连接");
            ui->pushButton_connect->setPalette(Pal1);
        }
        else
        {
            //断开连接
            socket->disconnectFromHost();
            socket->close();
            // 更新界面
            ui->pushButton_send->setEnabled(false);
            ui->pushButton_connect->setText("连接");
            ui->pushButton_connect->setPalette(Pal0);
        }
}

// 三、接受/读取数据:使用socket的write函数向客户端发送数据
void myWidget::socket_Read_Data()
{
    // 读取缓冲区数据
    QByteArray buffer= socket->readAll();
    if(!buffer.isEmpty())
    {
        QString str =ui->textEdit_receive->toPlainText();
        str += buffer+"\n";
        // 刷新显示接受到的数据
        ui->textEdit_receive->setText(str);
    }
}

// 四、发送按钮:使用socket的write函数向客户端发送数据
void myWidget::on_pushButton_send_clicked()
{
    //获取文本框内容并以ASCII码形式发送
    socket->write(ui->textEdit_send->toPlainText().toLatin1());
    socket->flush();    // 冲掉 缓存
}

// 五、断开连接
void myWidget::socket_Disconnected()
{
    ui->pushButton_send->setEnabled(false);
    QMessageBox::information(this, tr("提示"),tr("Disconnected!"), QMessageBox::Ok);
}

界面:
在这里插入图片描述

3、服务器

二、服务器

服务器使用到了QTcpSocket类和QTcpSever类。用到了6个步骤:
1)创建QTcpSever对象

server = new QTcpServer();

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

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

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

connect(server,&QTcpServer::newConnection,this,&mywidget::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();
4、服务器server示例

.pro文件添加:

QT        +=network

myWidget.h 添加:

//#include <QtNetwork>
#include <QTcpServer>
#include <QTcpSocket>
#include <QMessageBox>

namespace Ui {
class myWidget;
}

class myWidget : public QWidget
{
    Q_OBJECT

public:
    explicit myWidget(QWidget *parent = 0);
    ~myWidget();

private slots:
    void server_New_Connect();

    void socket_Read_Data();

    void socket_Disconnected();

    void on_pushButton_listen_clicked();

    void on_pushButton_send_clicked();
    
private:
    Ui::myWidget *ui;
private:
    QTcpServer  *server;
    QTcpSocket *socket;
    
	QPalette Pal0,Pal1; 	// 调色板
    bool socket_IsConnected =false ;
    
};    

myWidget.cpp 添加:

#include "mywidget.h"
#include "ui_mywidget.h"

myWidget::myWidget(QWidget *parent):QWidget(parent),ui(new Ui::myWidget)
{
    ui->setupUi(this);

    ui->lineEdit_port->setText("8010");
    ui->lineEdit_ip->setText(QNetworkInterface().allAddresses().at(1).toString());   //获取本地IP
    ui->lineEdit_ip->setEnabled(false);                     // 只能用主机IP 作为服务端
    ui->pushButton_send->setEnabled(false);

    Pal0=ui->pushButton_listen->palette();
    Pal1.setColor(QPalette::ButtonText,Qt::red);  // 此方式 只能对按钮文本、窗口文本的动态颜色设置

    // 一 、创建QTcpSever对象;
    server = new QTcpServer();
    //连接信号槽(服务端被访问时,自动触发newconnection 信号,绑定槽函数 server new connect)
    connect(server,&QTcpServer::newConnection,this,&myWidget::server_New_Connect);

}

myWidget::~myWidget()
{
    server->close();
    server->deleteLater();
    delete ui;
}

// 二、监听按钮:监听端口
void myWidget::on_pushButton_listen_clicked()
{
    if(ui->pushButton_listen->text()==tr("开始监听"))
    {
        // 1.获取端口号
        QHostAddress IP(ui->lineEdit_ip->text());   // 服务器IP
        int port = ui->lineEdit_port->text().toInt();
        // 2.监听指定的端口(主机地址)
        if(!server->listen(IP,port))
        {
            // 若出错,则输出错误信息
            QMessageBox::warning(this, tr("错误"),tr("监听失败!"), QMessageBox::Ok);
            return;
        }
        ui->pushButton_listen->setText("取消监听"); // 修改键文字
        ui->pushButton_listen->setPalette(Pal1);
       // ui->pushButton_listen->setStyleSheet("background-color:rgb(255,255,0)"); // 改变按钮背景颜色
    }
    else
    {
        //if(socket->state() == QAbstractSocket::ConnectedState) // 若socket没有指定对象会有异常
        if(socket_IsConnected)
        {
             //关闭连接
             socket->disconnectFromHost();
             socket_IsConnected =false;
         }
         // 4.关闭服务端
         server->close();
         QMessageBox::information(this, tr("提示"),tr("已取消监听"), QMessageBox::Ok);
         // 更新界面
         ui->pushButton_listen->setText("开始监听");
         ui->pushButton_listen->setPalette(Pal0);
         ui->pushButton_send->setEnabled(false);
     }
}

// 三、建立新连接(当服务器接收到客户端信号时)
void myWidget::server_New_Connect()
{
    //获取客户端连接(获得连接过来的客户端信息)
   socket = server->nextPendingConnection();
   //连接QTcpSocket的信号槽,以读取新数据(服务器接收到客户端数据后,自动触发 readyRead 信号)
   QObject::connect(socket, &QTcpSocket::readyRead, this, &myWidget::socket_Read_Data);
   // 关闭连接(客户端断开连接后,自动触发 disconnect 信号)
   QObject::connect(socket, &QTcpSocket::disconnected, this, &myWidget::socket_Disconnected);

   ui->pushButton_send->setEnabled(true);
   QMessageBox::information(this,tr("提示"),tr("A Client connect!"),QMessageBox::Ok);
   
   socket_IsConnected= true;
}
// 四、接受/读取数据:使用socket的write函数向客户端发送数据
void myWidget::socket_Read_Data()
{
    // 读取缓冲区数据
    QByteArray buffer= socket->readAll();
    if(!buffer.isEmpty())
    {
        QString str =ui->textEdit_receive->toPlainText();
        str +=buffer+"\n";
        // 刷新显示接受到的数据
        ui->textEdit_receive->setText(str);
    }
}

// 五、发送按钮:使用socket的write函数向客户端发送数据
void myWidget::on_pushButton_send_clicked()
{
    //获取文本框内容并以ASCII码形式发送(Latin1 编码规范)
    socket->write(ui->textEdit_send->toPlainText().toLatin1());
    socket->flush();
}

// 六、断开连接
void myWidget::socket_Disconnected()
{
    ui->pushButton_send->setEnabled(false);
    QMessageBox::information(this, tr("提示"),tr("Disconnected!"), QMessageBox::Ok);
}

界面:
在这里插入图片描述

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值