在标准C++没有提供专门用于套接字通信的类,所以只能使用操作系统提供的基于C的API函数,基于这些C的API函数我们也可以封装自己的C++类 C++套接字类的封装。但是Qt就不一样了,它是C++的一个框架并且里边提供了用于套接字通信的类(TCP、UDP)这样就使得我们的操作变得更加简单了(当然,在Qt中使用标准C的API进行套接字通信也是完全没有问题的)。下面,给大家讲一下使用相关类的进行TCP通信(关于TCP的更详细介绍在此不做展开)。
使用Qt提供的类进行基于TCP的套接字通信需要用到两个类:
QTcpServer:服务器类,用于监听客户端连接以及和客户端建立连接。
QTcpSocket:通信的套接字类,客户端、服务器端都需要使用。
这两个套接字通信类都属于网络模块network。在QT里我们如果想要使用这两个类,需要在项目的.pro或者是CMakeLists.txt文件里做如下操作(在QtCreator的帮助文档里都能找得到的):
CMake: find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake: QT += network
接下来我将介绍一下这两个类里的一些API函数。
1.QTcpServer
QTcpServer是服务器类,主要的作用是监听和连接客户端。
1.1公共函数
构造函数: QTcpServer::QTcpServer(QObject *parent = nullptr)
监听函数:bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0) 用于服务器监听来自地址和端口连接信号,其返回值为bool类型,参数一是ip地址,参数而是端口号。如果参数一是Any,那么服务器会监听所有address的连接信号。参数二port=0时是代表自动选择端口。监听成功返回true,反之false。
判断是否正在监听: bool QTcpServer::isListening() const
获取服务器地址:QHostAddress QTcpServer::serverAddress() const 如果当前服务器正在监听返回服务器地址,反之返回QHostAddress::Null。
获取服务器端口:quint16 QTcpServer::serverPort() const如果当前服务器正在监听返回服务器端口值,否则返回0。
得到和客户端建立连接之后的套接字对象:QTcpSocket *QTcpServer::nextPendingConnection()得到的对象是QTcpServer的一个子对象,QTcpServer析构时会自动析构这个子对象,当然也可以自己手动析构这个子对象。
阻塞等待客户端发起的连接请求:bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = nullptr)参数一为阻塞最大时长,参数二timeout判断是否超时。此函数不太适合于在单线程里使用,比他更合适于处理新连接的是信号newConnection()。
1.2信号
void QTcpServer::newConnection()这是新连接信号,每次新建连接都会发送此信号。
void QTcpServer::acceptError(QAbstractSocket::SocketError socketError)新连接出现错误会释放此信号,socketError参数会描述此错误。
2.QTcpSocket
QTcpSocket是一个套接字通信类,在服务器和客户端都会使用。Qt里的收发数据也属于IO操作(网络IO)
QTcpSocket继承了QAbstractSocket,后者又继承了QIODevice。
1.1成员函数
构造函数: QTcpSocket::QTcpSocket(QObject *parent = nullptr)
连接服务器(需指定端口号与IP地址):
[virtual] void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, QIODeviceBase::OpenMode openMode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)
void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, QIODeviceBase::OpenMode openMode = ReadWrite)
在Qt中不管调用读操作函数接收数据,还是调用写函数发送数据,操作的对象都是本地的由Qt框架维护的一块内存。因此,调用了发送函数数据不一定会马上被发送到网络中,调用了接收函数也不是直接从网络中接收数据,有缓冲区。关于底层的相关操作是不需要使用者来维护的。
接收数据
QByteArray QIODevice::read(qint64 maxSize) 指定可接收最大字节数,返回接收的字符串
qint64 QIODevice::read(char *data, qint64 maxSize)指定可接收最大字节数,maxSize指针指向data
QByteArray QIODevice::readAll() 读出当前所有可操作数据,以byte array的形式返回
发送数据
qint64 QIODevice::write(const char *data, qint64 maxSize)发送指针data指向内存里大小为maxSize的数据
qint64 QIODevice::write(const char *data)发送指针data指向内存里的数据,字符串以\0为标记
qint64 QIODevice::write(const char *data)发送指定字符串
2.2信号
void QIODevice::readyRead()表示对端数据发送成功,可以准备接收数据调用read函数
void QAbstractSocket::connected()调用connectToHost()函数并成功连接之后会发出该信号。
void QAbstractSocket::disconnected()套接字断开连接之后发出的信号
以上就是这两个类的一些基本API函数和信号。其实这里面的API函数很多,我无法面面俱到,只能提一下基础的。大家使用时可以直接查QtCreator里的帮助文档。
关于这些类在项目里的实战应用,我将在后面的文章里继续提。
水平有限,有错误之处多多包涵!
No responses yet