QT5实现简单的TCP通信的实现
作者:培培哥 发布时间:2023-11-02 21:24:48
这段时间用到了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的设计:
三、运行结果
附上两个工程的下载链接:tcp_QT_jb51.rar
来源:https://blog.csdn.net/u014695839/article/details/70041771


猜你喜欢
- 本文为大家分享了如何使用eclipse创建java项目,供大家参考,具体内容如下首先,打开Eclipse,在工具栏依次点击【File】>
- 在本次项目中,由于时间紧张直接使用DWR做Ajax请求!要求的是动态展示,那就需要使用DWR轮询请求,但是需要做异常情况下的一些处理!特别是
- 一、Android系统启动Android设备从按下开机键到桌面显示画面,大致过程如下图流程:开机显示桌面、从桌面点击 App 图标到 Act
- Spring容器可以在不使用<constructor-arg>和<property>元素的情况下自动装配相互协作的b
- 作者: juky_huang 事件的简单解释: 事件是对象发送的消息,以发信号通知操作的发生。操作可能是由用户交互(例如
- 一、代码@Componentpublic class BService { @Autowired &
- spring与IoCIoC:控制反转,将由代码操纵的对象控制权,交给第三方容器,反转给第三方容器。这种对象依赖的关系管理方式,称作IoC。I
- 工作中一直都是一个人奋战一人一个项目,使用maven管理,看这个也挺好,但是总感觉没有充分发挥maven的功能,于是研究了一下这个,网上关于
- try catch介绍我们编译运行程序出错的时候,编译器就会抛出异常。抛出异常要比终止程序灵活许多,这是因为Java提供了一个“捕获”异常的
- jpa之动态插入与修改(重写save)1.动态插入@Data@Entity@DynamicInsert@Table(name = "
- 前言相信大家对Android悬浮窗应该是很熟悉了,比如说腾讯视频、爱奇艺等APP都有悬浮窗功能。在你打游戏的同时还可以看视频,充分利用屏幕空
- WPF动画效果系列WPF实现动画效果(一)之基本概念WPF实现动画效果(二)之From/To/By 动画WPF实现动画效果(三)之时间线(T
- 一、字符串:1、访问String中的字符:string本身可看作一个Char数组。string s = "hello world&
- 最近经朋友介绍开始玩 密传 网络游戏 升级升级,突然觉得太费键盘,于是自己用C#写了一个程序,想代替我的操作,自己去打怪物,自己升级 用这个
- 有时我们获取到了页面需要在Java代码中进行解析,获取html中的数据,Jsoup是一个很方便的工具。一、什么是Jsoup?官网网站:htt
- 一. 关键字Java中的关键字是由特定的单词组成,单词全为小写字母,每个都有特殊的含义,其实Java关键字也就那几十个,这个不需要背,以后都
- 本文实例为大家分享了Android仿qq分组管理的第三方库,供大家参考,具体内容如下下面先看效果 我们点击展开与折叠分组的功能在库
- <?xml version="1.0" encoding="utf-8"?> <L
- 刚开始学习Service的时候以为它是一个线程的封装,也可以执行耗时操作。其实不然,Service是运行在主线程的。直接执行耗时操作是会阻塞
- 目录阻塞队列简介java中的阻塞队列BlockQueue中方法阻塞队列的实现原理总结阻塞队列简介阻塞队列(BlockingQueue)首先是