QT使用Socket通信

Socket通信


Qt中提供的所有的Socket类都是 非阻塞的。
Qt中常用的用于socket通信的套接字类:

  • QTcpServer用于TCP/IP通信, 作为服务器端套接字使用。
  • QTcpSocket用于TCP/IP通信,作为客户端套接字使用。
  • QUdpSocket用于UDP通信,服务器,客户端均使用此套接字。

TCP/IP


在Qt中实现TCP/IP服务器端通信的流程:

  • 创建套接字

  • 将套接字设置为监听模式

  • 等待并接受客户端请求
    可以通过QTcpServer提供的void newConnection()信号来检测是否有连接请求,如果有可以在对应的槽函数中调用nextPendingConnection函数获取到客户端的Socket信息(返回值为QTcpSocket*类型指针),通过此套接字与客户端之间进行通信。

  • 接收或者向客户端发送数据  接收数据:使用read()或者readAll()函数

  • 发送数据:使用write()函数

  • 客户端通信流程:

  • 1.创建套接字 ;

  • 2.连接服务器 可以使用QTcpSocket类的connectToHost()函数来连接服务器。

  • 3.向服务器发送或者接受数据 ;

    服务器端:

通过Qt提供的QTcpServer类实现服务器端的socket通信:

class TCPServer : public QMainWindow
{
    Q_OBJECT

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

public slots:
    void slotNewConnection();
    void slotReadyRead();

private:
    Ui::TCPServer *ui;
    // 负责监听的套接字
    QTcpServer* m_server;
    // 负责通信的套接字
    QTcpSocket* m_client;
};


//---------- tcpserver.cpp ------------
TCPServer::TCPServer(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::TCPServer),
    m_server(NULL),
    m_client(NULL)
{
    ui->setupUi(this);

    //创建套接字对象
    m_server = new QTcpServer(this);
    //将套接字设置为监听模式
    m_server->listen(QHostAddress::Any, 9999);

    //通过信号接收客户端请求
    connect(m_server, &QTcpServer::newConnection, 
this, &TCPServer::slotNewConnection);
}


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


void TCPServer::slotNewConnection()
{
    if(m_client == NULL)
    {
        //处理客户端的连接请求
        m_client = m_server->nextPendingConnection();
        //发送数据
        m_client->write("服务器连接成功!!!");
        //连接信号, 接收客户端数据
        connect(m_client, &QTcpSocket::readyRead, 
this, &TCPServer::slotReadyRead);
    }
}


void TCPServer::slotReadyRead()
{
    //接收数据
    QByteArray array = m_client->readAll();
    QMessageBox::information(this, "Client Message", array);
}

客户端:


客户端通过使用Qt提供的QTcpSocket类可以方便的实现与服务器端的通信。

//------------- tcpclient.h ------------
class TCPClient : public QMainWindow
{
    Q_OBJECT

public:
    explicit TCPClient(QWidget *parent = 0);
    ~TCPClient();
public slots:
    void slotReadyRead();
    void slotSendMsg();

private:
    Ui::TCPClient *ui;
    QTcpSocket* m_client;
};

//------------- tcpclient.cpp --------------
TCPClient::TCPClient(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::TCPClient)
{
    ui->setupUi(this);
    //创建套接字
    m_client = new QTcpSocket(this);
    //连接服务器
    m_client->connectToHost(QHostAddress("127.0.0.1"), 9999);

    //通过信号接收服务器数据
    connect(m_client, &QTcpSocket::readyRead, 
this, &TCPClient::slotReadyRead);
    //发送按钮
    connect(ui->btnSend, &QPushButton::clicked, 
this, &TCPClient::slotSendMsg);
}

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


void TCPClient::slotReadyRead()
{
	 //接收数据
    QByteArray array = m_client->readAll();
    QMessageBox::information(this, "Server Message", array);
}


void TCPClient::slotSendMsg()
{
    QString text = ui->textEdit->toPlainText();
	 //发送数据
    m_client->write(text.toUtf8());
    ui->textEdit->clear();
}

UDP:


使用Qt提供的QUdpSocket进行UDP通信。在UDP方式下,客户端并不与服务器建立连接,它只负责调用发送函数向服务器发送数据。类似的服务器也不从客户端接收连接,只负责调用接收函数,等待来自客户端的数据的到达。
在UDP通信中,服务器端和客户端的概念已经显得有些淡化,两部分做的工作都大致相同:

  • 创建套接字
  • 绑定套接字
    在UDP中如果需要接收数据则需要对套接字进行绑定,只发送数据则不需要对套接字进行绑定。
    通过调用bind()函数将套接字绑定到指定端口上。
  • 接收或者发送数据
    - 接收数据:使用readDatagram()接收数据,函数声明如下:
 		qint64	readDatagram(char * data, qint64 maxSize, 
					QHostAddress * address = 0, quint16 * port = 0)

//data: 接收数据的缓存地址
//maxSize: 缓存接收的最大字节数
//address: 数据发送方的地址(一般使用提供的默认值)
//port: 数据发送方的端口号(一般使用提供的默认值)

使用pendingDatagramSize()可以获取到将要接收的数据的大小,根据该函数返回值来准备对应大小的内存空间存放将要接收的数据。

  • 发送数据: 使用writeDatagram()函数发送数据,函数声明如下:
qint64	writeDatagram(const QByteArray & datagram, 
					const QHostAddress & host, quint16 port)
	//datagram:要发送的字符串
    //host:数据接收方的地址
    //port:数据接收方的端口号


广播:

  • 在使用QUdpSocket类的writeDatagram()函数发送数据的时候,其中第二个参数host应该指定为广播地址:QHostAddress::Broadcast此设置相当于QHostAddress(“255.255.255.255”)
    使用UDP广播的的特点:
  • 使用UDP进行广播,局域网内的其他的UDP用户全部可以收到广播的消息
  • UDP广播只能在局域网范围内使用

组播:


我们再使用广播发送消息的时候会发送给所有用户,但是有些用户是不想接受消息的,这时候我们就应该使用组播,接收方只有先注册到组播地址中才能收到组播消息,否则则接受不到消息。另外组播是可以在Internet中使用的。
在使用QUdpSocket类的writeDatagram()函数发送数据的时候,其中第二个参数host应该指定为组播地址,关于组播地址的分类:

  • 224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
  • 224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
  • 224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
  • 239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内;
    注册加入到组播地址需要使用QUdpSocket类的成员函数:
bool	joinMulticastGroup(const QHostAddress & groupAddress)

TCP/IP 和 UDP的区别:

						TCP/IP				UDP
	是否连接				面向连接			无连接
	传输方式				基于流			基于数据报
	传输可靠性			可靠			不可靠
	传输效率				效率低			效率高
	能否广播				不能			能

  • 21
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt 使用 socket 进行通信非常方便。你可以使用 Qt 提供的 QTcpSocket 类来进行 TCP 通信,或者使用 QUdpSocket 类来进行 UDP 通信。 首先,你需要在你的项目中包含相应的头文件: ```cpp #include <QTcpSocket> #include <QUdpSocket> ``` 接下来,你可以创建一个 QTcpSocket 或者 QUdpSocket 对象,并连接相应的信号和槽函数来处理通信事件。下面是一个使用 QTcpSocket 的例子: ```cpp QTcpSocket* socket = new QTcpSocket(this); connect(socket, &QTcpSocket::connected, [=]() { qDebug() << "Connected to server!"; }); connect(socket, &QTcpSocket::readyRead, [=]() { QByteArray data = socket->readAll(); qDebug() << "Received data: " << data; }); connect(socket, &QTcpSocket::disconnected, [=]() { qDebug() << "Disconnected from server!"; }); socket->connectToHost("127.0.0.1", 1234); // 连接到服务器的 IP 地址和端口号 // 发送数据 socket->write("Hello, server!"); // 关闭连接 socket->disconnectFromHost(); ``` 对于 UDP 通信,你可以使用 QUdpSocket 类的相应函数,如 `bind()`、`writeDatagram()` 和 `readyRead()` 来处理数据的发送和接收。下面是一个使用 QUdpSocket 的简单示例: ```cpp QUdpSocket* socket = new QUdpSocket(this); connect(socket, &QUdpSocket::readyRead, [=]() { while (socket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(socket->pendingDatagramSize()); QHostAddress sender; quint16 senderPort; socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); qDebug() << "Received datagram from: " << sender.toString(); qDebug() << "Data: " << datagram; } }); socket->bind(1234, QUdpSocket::ShareAddress); // 绑定本地端口号 // 发送数据报 QByteArray datagram = "Hello, server!"; socket->writeDatagram(datagram, QHostAddress("127.0.0.1"), 5678); ``` 这只是一个简单的示例,你可以根据你的实际需求来扩展和修改代码。希望对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值