【Qt】TCP连接--客户端和服务器

TCP连接时客户端和服务器做的(Linux里)

服务器

  1. socket
  2. bind
  3. listen
  4. accept
  5. send/recv
  6. close

客户端

  1. socket
  2. connect
  3. recv/send
  4. close

函数详见:

https://blog.csdn.net/l203018/article/details/130033648?fromshare=blogdetail&sharetype=blogdetail&sharerId=130033648&sharerefer=PC&sharesource=L203018&sharefrom=from_link


工程文件修改

使用qmake构建系统时,与网络数据库有关的项目在工程文件.pro中加上network,例如:

cpp 复制代码
QT += core gui network

若用CMake构建系统,用find_package找到 Qt 对应的模块(如网络模块 Network、数据库模块 Sql

cpp 复制代码
# Qt6 需明确指定COMPONENTS,Qt5语法类似但模块名可能略有差异
find_package(Qt6 COMPONENTS Core Network Sql REQUIRED)

要使用的头文件

套接字的头文件:<QTcpSocket>

IP地址:<QHostAddress>


服务器

  • 创建QTcpServer对象//服务器
  • 监听listen:ip和port
  • 连接信号和槽connect(客户端连接后server对象 发出的信号
  • 槽函数处理信号:建立Tcp连接

UI

服务器接收显示客户端的IP和端口。

头文件

在 Qt 中,服务器的监听 socket 被 QTcpServer 类封装,开发者无需直接调用底层socket()函数创建,而是通过QTcpServer对象间接使用。

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpServer>
#include<QTcpsocket>
#define PORT 8000

QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private:
    void newClientHandler();//连接新客户端
private:
    Ui::Widget *ui;
    QTcpServer *server;
};
#endif // WIDGET_H

cpp文件

建立TCP连接:

QTcpServer 调用 listen() 开始监听端口后,客户端通过 QTcpSocket::connectToHost() 发起连接请求时:

  1. 服务器会触发 **newConnection()**信号(表示有新连接到达)。
  2. 此时可调用 nextPendingConnection() 获取这个新连接对应的 QTcpSocket 指针

获取客户端地址: socket->peerAddress(); 返回**QHostAddress** 类型对象

获取客户端端口号: socket->peerPort(); 返回整数类型(quint16,无符号 16 位整数)

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    server = new QTcpServer;
    //监听IP和端口
    server->listen(QHostAddress::AnyIPv4,PORT);

    //客户端发起连接,server发出信号:newConnection
    connect(server,&QTcpServer::newConnection,this,&Widget::newClientHandler);
}

Widget::~Widget()
{
    delete ui;
}
//处理客户端
void Widget::newClientHandler()
{
    //建立TCP连接,返回地址
    QTcpSocket *socket = server->nextPendingConnection();

    ui->IPlineEdit->setText(socket->peerAddress().toString());
    ui->portlineEdit->setText(QString::number(socket->peerPort()));
}

客户端

创建一个QTcpsocket对象,connectToHost连接服务器

socket 套接字是接口"IP 地址 + 端口号" 标识了一个套接字端点 ,两个套接字(客户端和服务器)通过网络协议 (如 TCP、UDP)建立连接,实现数据收发。

常用信号:连接:connected;断开:disconnected

UI

填写要连接的服务器的ip地址和端口号,选择连接或断开(取消)。

头文件

创建一个socket对象

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QTcpSocket>
#include<QHostAddress>
#include<QMessageBox>


QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_cancelButton_clicked();

    void on_connectButton_clicked();

private:
    Ui::Widget *ui;
    QTcpSocket *socket;
};
#endif // WIDGET_H

cpp文件

socket对象要new

连接服务器:

socket->connectToHost(QHostAddress(IP),port.toShort());

按按钮的槽函数里面包括(处理连接和断开信号的connect,这里的处理函数直接用lambda表达式写了)

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    socket = new QTcpSocket;//创建socket对象
}

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

//按取消按钮的处理
void Widget::on_cancelButton_clicked()
{
    this->close();//关闭
}

//得到按连接按钮信号的处理
void Widget::on_connectButton_clicked()
{
    //获取ip地址和端口号
    QString IP = ui->IPEdit->text();
    QString port = ui->portEdit->text();

    //连接服务器
    socket->connectToHost(QHostAddress(IP),port.toShort());

    //连接成功会有一个socket发出的connected的信号
    connect(socket,&QTcpSocket::connected,[this]()
    {
        QMessageBox::information(this,"连接提示","连接服务器成功");
    });
    //连接断开socket发出信号
    connect(socket,&QTcpSocket::disconnected,[this]()
    {
        QMessageBox::warning(this,"连接提示","连接异常,网络断开");
    });

}

连接测试

127这个ip是本地环回测试地址。

指定服务器监听8000这个端口(服务器代码头文件中的#define PORT 8000)。

相关推荐
z202305081 小时前
Linux之vmlinux文件段布局和arm64 的链接脚本vmlinux.lds.S分析
linux·运维·服务器
百锦再2 小时前
第11章 泛型、trait与生命周期
android·网络·人工智能·python·golang·rust·go
濊繵2 小时前
Linux网络-Socket 编程 UDP
linux·网络·udp
Molesidy4 小时前
【VSCode】【Clangd】Win下的基于LLVM/Clangd+Clangd插件+MINGW+CMake的VSCode配置C/C++开发环境的详细教程
c++·ide·vscode·clangd·llvm
Mr_WangAndy5 小时前
C++_chapter13_C++并发与多线程_多线程概念,死锁,unique_lock(),lock_guard()使用
c++·lock·死锁·并发与多线程·unlock·lock_guard·unique_lock
Boop_wu5 小时前
[Java EE] 计算机基础
java·服务器·前端
小欣加油5 小时前
leetcode 946 验证栈序列
c++·算法·leetcode·职场和发展
神仙别闹5 小时前
基于QT(C++) 实现哈夫曼压缩(多线程)
java·c++·qt
小陈又菜6 小时前
【QT学习之路】网络通信新次元!Qt TCP双侠:Server监听瞬息,Socket连接万变
qt·网络协议·tcp/ip·socket
无敌最俊朗@6 小时前
C++ 并发与同步速查笔记(整理版)
开发语言·c++·算法