[Qt first entered the rivers and lakes] Detailed description of the underlying architecture and principles of Qt QTcpSocket

Yuxian: CSDN content partner, CSDN new star mentor, 51CTO (Top celebrity + expert blogger), github open source enthusiast (secondary development of go-zero source code, game back-end architecture https://github.com/Peakchen)

 

Qt QTcpSocket is a client and server class used to implement the TCP protocol. It can connect to a specified host and port, and provides a wealth of methods and signals to send and receive data. The underlying architecture of QTcpSocket consists of the following parts:

  1. QTcpSocketPrivate

QTcpSocketPrivate is a private class of QTcpSocket, which is responsible for the underlying implementation of QTcpSocket. QTcpSocketPrivate contains a member variable of QAbstractSocketEngine type, which is used to manage the underlying socket communication. In the constructor of QTcpSocket, a QTcpSocketPrivate object will be created and used as the private data of QTcpSocket.

  1. QAbstractSocketEngine

QAbstractSocketEngine is an abstract class that defines the interface of QTcpSocket underlying socket communication. The specific socket communication implementation is implemented by the QAbstractSocketEngine subclass of each platform. In QTcpSocketPrivate, a specific QAbstractSocketEngine subclass object will be created to implement the underlying socket communication of QTcpSocket.

  1. QSocketNotifier

QSocketNotifier is a class used in Qt to notify file descriptor status changes. It can monitor the read and write status of file descriptors and send signals to notify applications when the status changes. In QTcpSocketPrivate, QSocketNotifier is used to monitor the read and write status of the underlying socket communication, and a signal is sent to notify QTcpSocket when the status changes.

The following is the basic implementation architecture diagram of QTcpSocket:

+-------------------+
|      QTcpSocket    |
+-------------------+
| - socketDescriptor|
+-------------------+
          /_\
           |
           | 继承
           |
+-------------------+
|      QAbstractSocket |
+-------------------+
| - socketState     |
| - socketError     |
| - readBuffer      |
| - writeBuffer     |
| - readNotifier    |
| - writeNotifier   |
| - exceptionNotifier|
+-------------------+
          /_\
           |
           | 继承
           |
+-------------------+
|       QObject     |
+-------------------+

It can be seen that QTcpSocket inherits from two classes QAbstractSocket and QObject, among which QAbstractSocket provides basic socket operations (such as connecting, disconnecting, sending data, etc.), while QObject provides basic functions of objects (such as signals and slot, object name, etc.).

In the QTcpSocket class, the socketDescriptor attribute represents the socket descriptor used by the bottom layer, which is an integer value. In the constructor of QTcpSocket, a new socket will be created through the socket() function and associated with the socketDescriptor attribute. The connectToHost() function of QTcpSocket will call the underlying connect() function to establish a TCP connection. The bind() function of QTcpSocket will call the underlying bind() function to bind the socket to the specified local address and port. The listen() function of QTcpSocket will call the underlying listen() function to start listening for connection requests. The accept() function of QTcpSocket will call the underlying accept() function to accept the connection request and create a new socket.

QTcpSocket monitors the readable and writable events of the socket through the readNotifier and writeNotifier member variables. When the socket has data to read or write data, it will trigger the corresponding signal (such as readyRead and bytesWritten signal) to notify application. When a socket error occurs, the socketError signal will be triggered, and the application can handle the error through this signal.

In QTcpSocket, we can use the following methods to realize the communication between TCP client and server:

  1. connectToHost()

The connectToHost() method is used to connect to the specified host and port number. It accepts two parameters. The first parameter is a string indicating the host name or IP address to be connected, and the second parameter is an integer indicating the host name or IP address to be connected. The port number for the connection. For example:

QTcpSocket socket;
socket.connectToHost("www.example.com", 80);
  1. disconnectFromHost()

The disconnectFromHost() method is used to disconnect from the host, it does not accept any parameters. For example:

QTcpSocket socket;
socket.disconnectFromHost();
  1. write()

The write() method is used to send data to the connected host, and it accepts a byte array as a parameter, representing the data to be sent. For example:

QTcpSocket socket;
socket.write("Hello, world!");
  1. flush()

The flush() method is used to flush the buffer and send the data in the buffer. It does not accept any parameters. For example:

QTcpSocket socket;
socket.write("Hello, world!");
socket.flush();
  1. read()

The read() method is used to read data from the connected host, and it accepts an integer as a parameter, indicating the length of the data to be read. For example:

QTcpSocket socket;
socket.connectToHost("www.example.com", 80);
socket.write("GET / HTTP/1.0\r\n\r\n");
socket.flush();
QByteArray data = socket.readAll();
  1. close()

The close() method is used to close the socket, it does not accept any parameters. For example:

QTcpSocket socket;
socket.close();
  1. waitForConnected()

The waitForConnected() method is used to wait for the connection to complete. It accepts an integer as a parameter, indicating the timeout time (milliseconds) for waiting. For example:

QTcpSocket socket;
socket.connectToHost("www.example.com", 80);
if (socket.waitForConnected(5000)) {
    qDebug() << "Connected";
} else {
    qDebug() << "Connection timed out";
}
  1. waitForReadyRead()

The waitForReadyRead() method is used to wait for the socket to have data to read. It accepts an integer as a parameter, indicating the waiting timeout time (in milliseconds). For example:

QTcpSocket socket;
socket.connectToHost("www.example.com", 80);
socket.write("GET / HTTP/1.0\r\n\r\n");
socket.flush();
if(socket.waitForReadyRead(5000))) {
    QByteArray data = socket.readAll();
    qDebug() << data;
} else {
    qDebug() << "No data received";
}
  1. error()

The error() method is used to get the error code of the socket, which returns a value of QAbstractSocket::SocketError enumeration type. For example:

QTcpSocket socket;
socket.connectToHost("www.example.com", 80);
if (socket.waitForConnected(5000)) {
    qDebug() << "Connected";
} else {
    qDebug() << "Connection error:" << socket.error();
}

The above are the main methods of the QTcpSocket class. In addition, there are many other methods and signals, which can be selected and used according to actual needs. The following is a simple QTcpSocket sample code that demonstrates how to implement TCP client communication:

#include <QTcpSocket>
#include <QDebug>

int main()
{
    QTcpSocket socket;
    socket.connectToHost("www.example.com", 80);
    if (socket.waitForConnected(5000)) {
        qDebug() << "Connected";
        socket.write("GET / HTTP/1.0\r\n\r\n");
        socket.flush();
        if (socket.waitForReadyRead(5000)) {
            QByteArray data = socket.readAll();
            qDebug() << data;
        } else {
            qDebug() << "No data received";
        }
    } else {
        qDebug() << "Connection error:" << socket.error();
    }
    socket.close();
    return 0;
}

This sample code implements connecting to port 80 of www.example.com, sending an HTTP GET request, and reading the data returned by the server. In actual use, the code can be modified and extended as needed.

Guess you like

Origin blog.csdn.net/feng1790291543/article/details/131806916