QT基础(18)- QAbstractSocket
- 1 创建简单的客户端
- 2 QAbstractSocket
- 2.1 简介
- 2.2 枚举
- 2.2.1 BingFlag
- 2.2.2 NetworkLayerProtocol
- 2.2.3 PauseMode
- 2.2.4 SocketError
- 2.2.5 SocketOption
- 2.2.6 SocketType
- 2.2.7 SocketState
- 2.3 公有函数
- 2.3.1 构造函数
- 2.3.2 abort
- 2.3.3 bind
- 2.3.4 connectToHost
- 2.3.5 disconnectFromHost
- 2.3.6 error
- 2.3.7 flush
- 2.3.8 isValid
- 2.3.9 localAddress
- 2.3.10 localPort
- 2.3.11 pauseMode()
- 2.3.12 peerAddress
- 2.3.13 peerName
- 2.3.14 peerPort
- 2.3.15 protocolTag
- 2.3.16 proxy
- 2.3.17 resume
- 2.3.18 setPauseMode
- 2.3.19 setProtocolTag
- 2.3.20 readBufferSize
- 2.3.21 setReadBufferSize
- 2.3.22 setSocketDescriptor
- 2.3.23 setSocketOption
- 2.3.24 socketType
- 2.3.25 state
- 2.3.26 waitForConnected
- 2.3.27 waitForDisconnected
- 2.4 从父类中(QIODevice)重新实现的函数
- 2.4.1 atEnd
- 2.4.2 bytesAvailable
- 2.4.5 bytesWrite
- 2.4.6 canReadLine
- 2.4.7 close
- 2.4.8 isSequential
- 2.4.9 waitForBytesWritten
- 2.4.10 waitForReadyRead
- 2.5 信号
- `void connected()`
- `void disconnected()`
- `void errorOccurred(QAbstractSocket::SocketError socketError)`
- `void hostFound()`
- `void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)`
- `void stateChanged(QAbstractSocket::SocketState socketState)`
- 2.6 受保护的函数
- `void setLocalAddress(const QHostAddress &address)`
- `void setLocalPort(quint16 port)`
- `void setPeerAddress(const QHostAddress &address)`
- `void setPeerName(const QString &name)`
- `void setPeerPort(quint16 port)`
- `void setSocketError(QAbstractSocket::SocketError socketError)`
- `void setSocketState(QAbstractSocket::SocketState state)`
- 2.7 重新实现的保护函数
- `virtual qint64 readData(char *data, qint64 maxSize) override`
- `virtual qint64 readLineData(char *data, qint64 maxlen) override`
- `virtual qint64 writeData(const char *data, qint64 size) override`
1 创建简单的客户端
要建立一个TCP客户端其实是很容易的一般需要一下几步
- 包含QTcpSocket头文件:
#include <QTcpSocket>
- 创建QTcpSocket对象:
QTcpSocket* socket = new QTcpSocket(this);
- 连接服务器:
socket->connectToHost("192.168.1.106", 6000);
这里使用connectToHost函数连接服务器。如果连接成功,QTcpSocket会发出connected()信号;如果连接失败,会发出error()信号。
- 处理连接结果:
if(socket->waitForConnected()){
// 连接成功
} else {
// 连接失败
}
waitForConnected会阻塞进程
- 发送数据:
QString dataStr = "Hello";
socket->write(dataStr.toUtf8());
- 接收数据:
connect(socket, &QTcpSocket::readyRead, this, [&](){
QByteArray data = socket->readAll();
// 处理接收到的数据
});
使用readyRead()信号接收数据,然后使用readAll()函数读取接收到的数据。注意,readyRead()信号可能会被多次触发,所以要使用while循环读取所有数据。
- 断开连接:
socket->disconnectFromHost();
使用disconnectFromHost()函数断开与服务器的连接。
2 QAbstractSocket
2.1 简介
以下内容来自官方,本人认为已经讲解的非常清晰明了:
QAbstractSocket是QTcpSocket和QUdpSocket的基类,包含这两个类的所有共同功能。如果需要使用套接字,可以选择以下两种方式:
- 实例化QTcpSocket或QUdpSocket。
- 创建原生套接字描述符,实例化QAbstractSocket,并调用setSocketDescriptor()函数将原生套接字包装起来。
TCP(传输控制协议)是一种可靠的、面向流的、面向连接的传输协议。UDP(用户数据报协议)是一种不可靠的、面向数据报的、无连接的协议。实际上,这意味着TCP更适合于连续传输数据,而更轻量级的UDP可以在可靠性不重要的情况下使用。
QAbstractSocket的API统一了这两种协议之间的大部分差异。例如,虽然UDP是无连接的,但connectToHost()函数为UDP套接字建立了一个虚拟连接,使得可以使用QAbstractSocket在底层协议不同的情况下使用相同的方式。在内部,QAbstractSocket会记住传递给connectToHost()的地址和端口号,并使用这些值来执行read()和write()等函数。
在任何时候,QAbstractSocket都有一个状态(通过state()函数返回)。初始状态是UnconnectedState。在调用connectToHost()之后,套接字首先进入HostLookupState状态。如果找到主机,QAbstractSocket进入ConnectingState状态并发出hostFound()信号。当连接建立后,它进入ConnectedState状态并发出connected()信号。如果在任何阶段出现错误,则发出errorOccurred()信号。每当状态发生变化时,都会发出stateChanged()信号。为方便起见,isValid()函数返回套接字是否准备好读写,但是请注意,在读写之前,套接字的状态必须是ConnectedState。
通过调用read()或write()函数读取或写入数据,或使用readLine()和readAll()等方便函数。QAbstractSocket还从QIODevice继承了getChar()、putChar()和ungetChar(),可以用于单字节。当数据已写入套接字时,将发出bytesWritten()信号。请注意,Qt不限制写缓冲区大小。可以通过侦听此信号来监视其大小。
每次新的数据块到达时,将发出readyRead()信号。然后,bytesAvailable()返回可供读取的字节数。通常,会将readyRead()信号连接到槽,并在那里读取所有可用的数据。如果没有一次读取所有数据,则剩余的数据仍将在稍后可用,并且任何新的传入数据将附加到QAbstractSocket的内部读取缓冲区中。要限制读取缓冲区的大小,请调用setReadBufferSize()。
要关闭套接字,请调用disconnectFromHost()函数。QAbstractSocket进入QAbstractSocket::ClosingState状态。在所有挂起的数据都写入套接字后,QAbstractSocket实际上关闭套接字,进入QAbstractSocket::UnconnectedState状态,并发出disconnected()信号。如果要立即中止连接,并放弃所有挂起的数据,请调用abort()函数。如果远程主机关闭了连接,则QAbstractSocket将发出errorOccurred(QAbstractSocket::RemoteHostClosedError)信号,在此期间,套接字状态仍为ConnectedState,然后发出disconnected()信号。
已连接对等体的端口和地址可以通过调用peerPort()和peerAddress()函数获取。peerName()函数返回传递给connectToHost()的对等体主机名。localPort()和localAddress()返回本地套接字的端口和地址。
QAbstractSocket提供了一组函数,可以暂停调用线程,直到某些信号被发出。可以使用这些函数来实现阻塞套接字:
waitForConnected()函数会阻塞,直到建立连接。
waitForReadyRead()函数会阻塞,直到有新数据可供读取。
waitForBytesWritten()函数会阻塞,直到一次有效载荷的数据已写入套接字。
waitForDisconnected()函数会阻塞,直到连接关闭。
我们以一个示例来说明:
int numRead = 0, numReadTotal = 0;
char buffer[50];
while (true) {
numRead = socket.read(buffer, 50);
// 对数组做处理
numReadTotal += numRead;
if (numRead == 0 && !socket.waitForReadyRead()) {
break;
}
}
如果waitForReadyRead()返回false,则连接已关闭或发生错误。
使用阻塞套接字的编程与使用非阻塞套接字的编程有根本的不同。阻塞套接字不需要事件循环,通常导致代码更简单。然而,在GUI应用程序中,应该只在非GUI线程中使用阻塞套接字,以避免冻结用户界面。有关两种方法的概述,请参见fortuneclient和blockingfortuneclient示例。
注意:我们不建议将阻塞函数与信号一起使用。应该使用这两种可能性之一。
QAbstractSocket可以与QTextStream和QDataStream的流运算符(operator<<()和operator>>())一起使用。但是,需要注意一个问题:在尝试使用operator>>()读取数据之前,必须确保有足够的数据可用。
QAbstractSocket是一个抽象类,不能直接创建对象。它被用作QTcpSocket和QUdpSocket的基类,以提供这两个类的公共功能
2.2 枚举
2.2.1 BingFlag
用于在绑定套接字时指定绑定选项
2.2.2 NetworkLayerProtocol
用于指定套接字使用的网络层协议
2.2.3 PauseMode
2.2.4 SocketError
2.2.5 SocketOption
QAbstractSocket::SocketOption枚举类型表示可在套接字上设置的选项。在收到与套接字建立连接的connected()信号或从QTcpServer接收到新套接字之后,可以设置这些选项。
常量 | 描述 |
---|---|
QAbstractSocket::LowDelayOption | 尝试优化套接字以实现低延迟。对于QTcpSocket,这将设置TCP_NODELAY选项并禁用Nagle算法。将其设置为1以启用。QAbstractSocket::LowDelayOption是一个用于优化套接字以实现低延迟的选项。对于QTcpSocket来说,设置此选项会启用TCP_NODELAY选项,并禁用Nagle算法,这些都可以减少套接字数据传输时的延迟。这在需要实时数据传输的应用程序中非常有用,如在线游戏或视频流。在这些应用程序中,即使少量的延迟也可能导致用户体验的显著下降。因此,通过设置此选项可以使套接字优化其行为,以便实现更低的延迟。 |
QAbstractSocket::KeepAliveOption | 将此设置为1以启用SO_KEEPALIVE套接字选项。QAbstractSocket::KeepAliveOption是一个套接字选项,用于启用/禁用套接字上的SO_KEEPALIVE功能。启用此选项后,操作系统将定期检查套接字连接的对端是否仍然存在。如果发现对端不存在,操作系统将关闭套接字连接,并且可以触发一个连接断开的信号。这可以帮助检测连接断开的情况,例如在无法及时处理网络连接时,可能会发生应用程序崩溃等情况。但是,应该注意,启用此选项会在套接字上引入一定的开销,因此不应该在不需要时启用它,以免浪费资源。 |
QAbstractSocket::MulticastTtlOption | 将此值设置为整数值以设置IP_MULTICAST_TTL(组播数据报的TTL)套接字选项。QAbstractSocket::MulticastTtlOption是一个套接字选项,用于设置多播数据报的TTL(生存时间)。TTL是一个整数值,表示多播数据报可以被转发的最大次数。每次多播数据报从一个路由器传递到另一个路由器时,其TTL值都会减少1。当TTL值减为0时,多播数据报将被丢弃。通过设置此选项,你可以控制多播数据报的传递范围,从而避免不必要的网络流量或确保多播数据报只在局域网内传递。这对于一些需要向多个计算机广播信息的应用程序非常有用,如视频流或在线游戏。 |
QAbstractSocket::MulticastLoopbackOption | 将此设置为1以启用IP_MULTICAST_LOOP(组播环回)套接字选项。 |
QAbstractSocket::TypeOfServiceOption | 此选项在Windows上不受支持。这映射到IP_TOS套接字选项。有关可能的值,请参见下表。 |
QAbstractSocket::SendBufferSizeSocketOption | 在操作系统级别设置套接字发送缓冲区大小(以字节为单位)。这将映射到SO_SNDBUF套接字选项。此选项不会影响QIODevice或QAbstractSocket缓冲区。此枚举值已在Qt 5.3中引入。 |
QAbstractSocket::ReceiveBufferSizeSocketOption | 在操作系统级别设置套接字接收缓冲区大小(以字节为单位)。这将映射到SO_RCVBUF套接字选项。此选项不会影响QIODevice或QAbstractSocket缓冲区(请参阅setReadBufferSize())。此枚举值已在Qt 5.3中引入。 |
QAbstractSocket::PathMtuSocketOption | 检索IP堆栈当前已知的路径最大传输单元(PMTU)值(如果有)。某些IP堆栈还允许设置用于传输的MTU。此枚举值是在Qt 5.11中引入的。 |
2.2.6 SocketType
常量 | 描述 |
---|---|
QAbstractSocket::TcpSocket | TCP套接字。 |
QAbstractSocket::UdpSocket | UDP套接字。 |
QAbstractSocket::SctpSocket | SCTP套接字(从Qt 5.12开始支持)。 |
QAbstractSocket::UnknownSocketType | 除了TCP,UDP和SCTP |
2.2.7 SocketState
enum QAbstractSocket::SocketState
常量 | 描述 |
---|---|
QAbstractSocket::UnconnectedState | 未连接状态 |
QAbstractSocket::HostLookupState | 正在查找主机状态 |
QAbstractSocket::ConnectingState | 正在连接状态 |
QAbstractSocket::ConnectedState | 已连接状态 |
QAbstractSocket::BoundState | 已绑定状态 |
QAbstractSocket::ClosingState | 正在关闭状态 |
QAbstractSocket::ListeningState | 监听状态 |
2.3 公有函数
2.3.1 构造函数
QAbstractSocket::QAbstractSocket(QAbstractSocket::SocketType socketType, QObject *parent)
参数socketType指定套接字的类型(参考2.2.6)
参数parent是可选的,指定该对象的父对象。默认值为nullptr。
QAbstractSocket是一个抽象类,不能直接创建对象。它被用作QTcpSocket和QUdpSocket的基类,以提供这两个类的公共功能。
2.3.2 abort
void QAbstractSocket::abort()
QAbstractSocket::abort()是一个公共函数,用于立即终止套接字上的任何当前操作,并关闭套接字。与disconnectFromHost()不同,abort()不会等待套接字上的缓冲区被刷新或任何未完成的操作完成。它会立即关闭套接字连接并发出disconnected()信号,这可能会导致丢失未发送或未接收的数据。通常,应在需要尽快关闭套接字连接的情况下使用此函数,例如在用户主动关闭应用程序或发生错误时。
2.3.3 bind
bool QAbstractSocket::bind(const QHostAddress &address, quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)
QAbstractSocket::bind()函数是用于在本地套接字上绑定地址和端口的公共函数。它接受三个参数,其中第一个参数是一个QHostAddress类型的对象,表示要绑定的IP地址;第二个参数是一个整数,表示要绑定的端口号;第三个参数是一个枚举类型的值,表示要使用的绑定模式,默认值为DefaultForPlatform。
如果未指定端口号,则系统会为套接字分配一个可用端口。如果绑定成功,则返回true,否则返回false。
该函数用于将套接字绑定到指定的地址和端口,其中的BindMode参数表示绑定模式。对于UDP套接字,绑定后,每当UDP数据报到达指定的地址和端口时,都会发出QUdpSocket::readyRead()信号。因此,该函数对编写UDP服务器很有用。对于TCP套接字,此函数可用于指定用于传出连接的接口,这在存在多个网络接口的情况下非常有用。默认情况下,使用DefaultForPlatform BindMode绑定套接字。如果未指定端口,则选择随机端口。如果成功绑定,则函数返回,并且套接字进入BoundState;否则返回false。该函数在
bool bind(quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)
这是一个重载函数。
该函数将套接字绑定到QHostAddress::Any地址和指定的端口,其中的BindMode参数表示绑定模式。QHostAddress::Any表示该套接字将绑定到所有可用网络接口的地址。默认情况下,使用DefaultForPlatform BindMode绑定套接字。如果未指定端口,则选择随机端口。如果成功绑定,则函数返回,并且套接字进入BoundState;否则返回false。
2.3.4 connectToHost
virtual void connectToHost(const QString &hostName, quint16 port, QIODevice::OpenMode openMode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)
该函数用于在TCP模式下连接到远程主机。它将套接字连接到主机名为hostName和端口为port的远程主机。其中openMode参数表示打开模式,可设置为ReadWrite(默认值)或ReadOnly。NetworkLayerProtocol参数protocol表示连接使用的网络协议,默认值为AnyIPProtocol,表示Qt将自动选择最佳协议。
如果连接成功,则QTcpSocket将发出connected()信号,可以在连接成功后读写套接字。如果连接失败,则发出errorOccurred()信号。在连接期间,QAbstractSocket处于ConnectingState状态。
virtual void connectToHost(const QHostAddress &address, quint16 port, QIODevice::OpenMode openMode = ReadWrite)
该函数用于在TCP模式下连接到远程主机。它将套接字连接到指定地址为address和端口为port的远程主机。其中openMode参数表示打开模式,可设置为ReadWrite(默认值)或ReadOnly。
如果连接成功,则QTcpSocket将发出connected()信号,可以在连接成功后读写套接字。如果连接失败,则发出errorOccurred()信号。在连接期间,QAbstractSocket处于ConnectingState状态。
2.3.5 disconnectFromHost
void QAbstractSocket::disconnectFromHost()
该函数用于断开与主机的连接,关闭套接字并将QAbstractSocket的状态设置为UnconnectedState。当与主机的连接被断开并且所有待处理的数据已经被传输时,将发出disconnected()信号。如果套接字未连接,则函数什么也不做。
***与close()函数不同,disconnectFromHost()不会立即关闭套接字,而是等待所有数据传输完成。***可以使用waitForDisconnected()函数阻塞,直到套接字已经断开连接。在断开连接之前,还可以使用abort()函数强制断开连接并立即关闭套接字。
2.3.6 error
QAbstractSocket::SocketError QAbstractSocket::error() const
QAbstractSocket::error()是一个成员函数,用于返回上一次发生的错误类型。当连接建立时,可以通过调用此函数获取连接是否成功。当连接断开或发生错误时,此函数也可以用于获取错误类型。QAbstractSocket::SocketError是一个枚举类型,表示可能发生的错误类型,例如连接被拒绝、连接超时、远程主机关闭连接等。在调用此函数之前,必须先连接errorOccurred()信号,以便在发生错误时及时处理。
QAbstractSocket::SocketError见2.2.4
errorString()可以描述错误的字符串
2.3.7 flush
bool QAbstractSocket::flush()
flush() 函数用于强制将写缓冲区中的数据写入套接字。该函数返回 true 表示写缓冲区的所有数据已成功写入套接字,否则返回 false。
如果您使用的是 QTcpSocket 或 QUdpSocket 类,则 flush() 函数会立即将数据写入网络。如果您使用的是其它类型的套接字,则该函数只是将数据写入内核的套接字缓冲区,而不是立即写入网络。写入网络的时间可能会受到许多因素的影响,例如网络拥塞、远程主机的可用性等。
2.3.8 isValid
bool QAbstractSocket::isValid() const
QAbstractSocket::isValid()函数返回一个布尔值,指示当前套接字是否可用于读取和写入数据。如果套接字已连接且没有发生错误,则返回true;否则返回false。
在使用套接字之前,应该先检查套接字的有效性,以确保可以成功读写数据。如果套接字无效,则所有的读写操作都将失败。
2.3.9 localAddress
QHostAddress QAbstractSocket::localAddress() const
返回本地绑定的地址。在使用bind()函数绑定地址和端口之后,可以使用该函数获取本地地址。
如果尚未绑定套接字,则该函数将返回QHostAddress::Null。
2.3.10 localPort
quint16 QAbstractSocket::localPort() const
返回绑定的端口
2.3.11 pauseMode()
QAbstractSocket::PauseModes pauseMode() const
QAbstractSocket::PauseModes 是 QAbstractSocket 类的一个枚举值,它表示当前套接字的暂停模式。暂停模式包括 ReadPause 和 WritePause,它们分别表示套接字的读取和写入是否被暂停。在某些情况下,例如当套接字写入缓冲区已满时,套接字可能会自动暂停写入。可以通过调用 setReadPause() 和 setWritePause() 方法来手动设置套接字的暂停模式。使用 pauseMode() 方法可以查询当前暂停模式。
QAbstractSocket::PauseModes 见2.2.3
2.3.12 peerAddress
QHostAddress QAbstractSocket::peerAddress() const
该函数返回与套接字连接的对等端地址。对于TCP套接字,它返回对等端的IP地址;对于UDP套接字,它返回上次收到数据报的发送方的IP地址。如果该套接字没有连接,则返回QHostAddress::Null。
2.3.13 peerName
QString QAbstractSocket::peerName() const
QAbstractSocket::peerName()函数返回已连接套接字的对等端主机名称。如果没有连接,该函数将返回一个空字符串。
对于TCP套接字,这个名称是在connectToHost()函数中指定的主机名。对于UDP套接字,这个名称是在readDatagram()函数中接收到的数据报的源地址中解析出来的。
注意,peerName()函数只返回主机名,而不返回端口号。要获取对等端套接字的端口号,可以使用peerAddress()函数并检查其端口号。
2.3.14 peerPort
quint16 QAbstractSocket::peerPort() const
函数返回与此套接字连接的远程端口。如果套接字没有连接,则返回0。
例如,如果您使用QTcpSocket类连接到服务器并与服务器建立连接,则可以使用此函数获取远程服务器的端口。
2.3.15 protocolTag
QString QAbstractSocket::protocolTag() const
QString QAbstractSocket::protocolTag() const 返回用于此套接字的协议标记,如果未设置,则返回一个空字符串。
协议标记是一个字符串,它标识套接字的网络协议类型。该标记通常用于跨线程或跨网络传递套接字,以便在需要时可以轻松地重新创建套接字。
此函数适用于QTcpSocket、QUdpSocket和QSctpSocket。
注意,对于已连接的套接字,协议标记应始终为默认值。只有在套接字未连接时才应设置协议标记。
此函数是虚拟的,并且在子类中可以重新实现以提供特定于协议的标记。
2.3.16 proxy
QNetworkProxy QAbstractSocket::proxy() const
void setProxy(const QNetworkProxy &networkProxy)
QAbstractSocket::proxy()函数返回当前套接字的网络代理对象,用于与远程主机通信时使用的代理服务器。如果没有设置代理,则返回默认构造的QNetworkProxy对象。
常量 | 描述 |
---|---|
QNetworkProxy::NoProxy | 不使用代理 |
QNetworkProxy::DefaultProxy | 代理是根据使用setApplicationProxy 设置的应用程序代理确定的() |
QNetworkProxy::Socks5Proxy | Socks5代理 |
QNetworkProxy::HttpProxy | 使用 HTTP 透明代理 |
QNetworkProxy::HttpCachingProxy | 仅代理 HTTP 请求 |
QNetworkProxy::FtpCachingProxy | 仅代理 FTP 请求 |
2.3.17 resume
void QAbstractSocket::resume()
该函数用于恢复套接字的数据传输。如果调用了pause()暂停数据传输,则可以使用该函数来恢复数据传输。
注意,如果套接字已经是活动状态,则该函数不会起作用。
2.3.18 setPauseMode
void QAbstractSocket::setPauseMode(QAbstractSocket::PauseModes pauseMode)
该函数用于控制是否在接收到某些通知时暂停数据传输。其中pauseMode参数指定了在什么条件下套接字应该被暂停。目前支持的通知仅为QSslSocket::sslErrors()。如果设置为PauseOnSslErrors,则在套接字上的数据传输将被暂停,并需要通过调用resume()显式地重新启用。默认情况下,此选项设置为PauseNever。必须在连接到服务器之前调用此选项,否则将导致未定义的行为。
2.3.19 setProtocolTag
void QAbstractSocket::setProtocolTag(const QString &tag)
该函数为 QAbstractSocket 新增的函数,在 Qt 5.14 版本中引入。该函数用于设置协议标签,即标识使用的协议。通常情况下,Qt 网络库能够自动检测所使用的协议,但在某些情况下,如果有多种协议可以使用,就需要手动指定协议标签。例如,对于 QTcpSocket,可以通过调用此函数来设置 HTTP/1.1 或 HTTP/2。
2.3.20 readBufferSize
qint64 QAbstractSocket::readBufferSize() const
QAbstractSocket::readBufferSize()函数返回当前套接字接收缓冲区大小(以字节为单位)。默认值是0,表示使用系统默认值。
注意:这个函数返回的是套接字的缓冲区大小,不是已经接收到的数据的大小。要获取已经接收到的数据的大小,可以使用bytesAvailable()函数。
如果你想改变缓冲区大小,可以使用setReadBufferSize()函数。
2.3.21 setReadBufferSize
void QAbstractSocket::setReadBufferSize(qint64 size)
void QAbstractSocket::setReadBufferSize(qint64 size)函数用于设置QAbstractSocket的内部读取缓冲区大小为size字节。
如果将缓冲区大小限制为某个特定大小,则QAbstractSocket不会缓冲超过该大小的数据。特别地,缓冲区大小为0意味着读取缓冲区无限制,所有传入的数据都将被缓冲。这是默认值。
此选项在以下情况下很有用:如果您仅在特定时间点读取数据(例如,在实时流应用程序中),或者如果您希望保护套接字免受接收过多数据的影响,这可能会导致应用程序内存不足。
仅QTcpSocket使用QAbstractSocket的内部缓冲区;QUdpSocket根本不使用任何缓冲,而是依赖于操作系统提供的隐式缓冲。因此,在QUdpSocket上调用此函数没有任何效果。
2.3.22 setSocketDescriptor
virtual bool setSocketDescriptor(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = ConnectedState, QIODevice::OpenMode openMode = ReadWrite)
virtual qintptr socketDescriptor() const
将现有套接字的描述符设置为QAbstractSocket的描述符,同时将状态设置为socketState并打开openMode。
此函数可用于将现有的原始套接字或操作系统文件描述符与QAbstractSocket实例关联,从而使其能够使用Qt套接字接口。如果传递的socketDescriptor不是有效的套接字描述符,则此函数返回false,否则返回true。
该函数仅在Unix和Windows上受支持,并且需要使用qintptr类型的套接字描述符。在Windows上,使用强制类型转换将SOCKET类型转换为qintptr。
如果成功,则QAbstractSocket进入ConnectedState,否则进入UnconnectedState。默认情况下,打开模式为ReadWrite。
2.3.23 setSocketOption
virtual void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
virtual QVariant socketOption(QAbstractSocket::SocketOption option)
设置套接字选项。option 参数指定选项,value 参数指定选项值。这个函数可用于设置选项,例如 QAbstractSocket::LowDelayOption 和 QAbstractSocket::KeepAliveOption。
这个函数可以在任何时间调用,包括连接建立后和传输期间。但是,并非所有套接字实现都支持所有选项。如果尝试设置不支持的选项,则会发出 QAbstractSocket::SocketError 信号。
请注意,对于某些套接字选项,必须在连接到主机之前调用此函数。例如,要在连接到主机之前设置 QAbstractSocket::LowDelayOption 选项,则必须在调用 connectToHost() 函数之前调用 setSocketOption()。
如果值无效,则不会发出信号并返回 false。否则,返回 true。
此函数是虚函数,因此可以在继承 QAbstractSocket 类的任何子类中重新实现它以添加特定于协议或特定于实现的选项。
2.3.24 socketType
QAbstractSocket::SocketType socketType() const
QAbstractSocket::SocketType socketType() const 返回当前套接字的类型,可以是 UnknownSocketType,TcpSocket,或者 UdpSocket。可以使用 setSocketType() 函数设置套接字类型。
2.3.25 state
QAbstractSocket::SocketState QAbstractSocket::state() const
连接状态
2.3.26 waitForConnected
bool QAbstractSocket::waitForConnected(int msecs = 30000)
waitForConnected函数是阻塞式的函数,用于等待socket连接到主机。
函数会一直阻塞直到连接成功,或者超时,或者连接出错。
参数msecs表示最大等待时间(单位为毫秒),默认为30秒。如果在规定时间内连接成功,则函数返回true,否则返回false。在连接成功前,该函数不会返回。
2.3.27 waitForDisconnected
bool QAbstractSocket::waitForDisconnected(int msecs = 30000)
是一个阻塞函数,用于等待socket与主机的断开连接。该函数会一直阻塞直到socket断开连接或者等待时间超时。如果在规定时间内连接断开,该函数返回true,否则返回false。
该函数可以传入一个可选参数msecs,用于设置等待的超时时间,单位为毫秒,默认为30000毫秒(30秒)。如果等待时间超过了这个时间仍然没有收到断开连接的信号,函数就会返回false。
2.4 从父类中(QIODevice)重新实现的函数
2.4.1 atEnd
bool QAbstractSocket::atEnd() const
QAbstractSocket::atEnd()是QIODevice类的成员函数,用于判断当前输入缓冲区是否已读完。对于QAbstractSocket而言,该函数用于判断当前接收缓冲区是否为空。
如果当前接收缓冲区为空,该函数将返回true,否则返回false。
需要注意的是,atEnd()函数只是判断当前缓冲区是否为空,并不会从socket中读取任何数据。如果想要从socket中读取数据,需要调用read()或者readAll()等函数
2.4.2 bytesAvailable
qint64 QAbstractSocket::bytesAvailable() const
函数 bytesAvailable() 返回了当前 socket 缓冲区中可供读取的字节数量。如果在可读取的缓冲区中没有数据可用,则此函数返回 0。
2.4.5 bytesWrite
qint64 QAbstractSocket::bytesToWrite() const
QAbstractSocket::bytesToWrite()函数返回缓冲区中还未发送的数据字节数。对于TCP套接字,该函数返回缓冲区中还未被发送的字节数,对于UDP套接字,该函数返回尚未被接收的数据报数量。该函数通常用于实现流量控制和同步写操作,以确保在写入大量数据之前套接字缓冲区具有足够的空间,从而避免写入阻塞。
2.4.6 canReadLine
bool QAbstractSocket::canReadLine() const
bool QAbstractSocket::canReadLine() const 函数用于判断当前 QAbstractSocket 的输入缓冲区中是否已经存在一行完整的数据。在 QIODevice 中,一行数据是以行结束符(例如 \n 或者 \r\n)作为结尾的数据,canReadLine() 函数能够检测到是否存在这样的一行数据。如果存在,则返回 true,否则返回 false。
2.4.7 close
void QAbstractSocket::close()
void QAbstractSocket::close() 关闭套接字,使套接字进入UnconnectedState状态,并释放其所有资源。
当调用此函数时,套接字会尝试将所有未写入的数据发送到对等方,并关闭套接字。请注意,它并不等待所有数据都写入,而是在尽力而为后立即关闭套接字。
关闭套接字后,将不再发出readyRead()信号。任何尝试读取套接字的操作将返回-1,并将error()设置为QAbstractSocket::RemoteHostClosedError。在大多数操作系统上,包括Unix和Windows,另一端可以重用同一端口。
在QTcpSocket中,如果套接字进入ClosingState,则需要等待disconnected()信号才能在重新使用相同的QTcpSocket之前进行重新连接。
调用close()后,不能再调用connectToHost()或connectToServer()。
2.4.8 isSequential
bool QAbstractSocket::isSequential() const
isSequential()是QIODevice类中的一个函数,QAbstractSocket类是QIODevice类的子类,因此它也继承了这个函数。该函数用于判断设备是否以连续的方式传输数据。对于QAbstractSocket类来说,由于它是一个网络套接字,数据是通过网络发送和接收的,因此它不是一个连续的设备,isSequential()函数会返回false。
2.4.9 waitForBytesWritten
bool QAbstractSocket::waitForBytesWritten(int msecs = 30000)
QAbstractSocket::waitForBytesWritten()是一个阻塞函数,它会等待套接字缓冲区的数据被完全写入,或者直到超时时间msecs到达为止。
该函数返回true表示套接字缓冲区的数据已经被完全写入,返回false表示在超时时间内未完成写入。在返回false时,应用程序可以通过error()函数判断错误原因,例如超时、写入错误等。
2.4.10 waitForReadyRead
bool QAbstractSocket::waitForReadyRead(int msecs = 30000)
bool QAbstractSocket::waitForReadyRead(int msecs = 30000)函数会阻塞当前线程,直到有新数据可读,或者超时指定的时间。如果在超时时间内有新数据可读,则返回 true,否则返回 false。
该函数的参数 msecs 指定了最长的等待时间,单位为毫秒,默认为 30000 毫秒(30 秒)。如果设置为 -1,则表示一直等待,直到有新数据可读。
该函数一般用于同步读取数据的场景。对于异步读取数据,应当使用信号槽机制,通过连接 readyRead() 信号实现。
2.5 信号
void connected()
void disconnected()
void errorOccurred(QAbstractSocket::SocketError socketError)
void hostFound()
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
void stateChanged(QAbstractSocket::SocketState socketState)
函数 | 描述 |
---|---|
connected() | 连接建立时发送该信号。 |
disconnected() | 断开连接时发送该信号。 |
errorOccurred(QAbstractSocket::SocketError socketError) | 在发生错误时发送该信号,参数 socketError 是错误的类型。 |
hostFound() | 当 QAbstractSocket 开始查找主机时发送该信号。 |
proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) | 当需要进行代理身份验证时发送该信号,参数 proxy 是要使用的代理,参数 authenticator 是指向要使用的 QAuthenticator 的指针。 |
stateChanged(QAbstractSocket::SocketState socketState) | 当 socket 状态发生更改时发送该信号,参数 socketState 是新状态的值。 |
2.6 受保护的函数
void setLocalAddress(const QHostAddress &address)
void setLocalPort(quint16 port)
void setPeerAddress(const QHostAddress &address)
void setPeerName(const QString &name)
void setPeerPort(quint16 port)
void setSocketError(QAbstractSocket::SocketError socketError)
void setSocketState(QAbstractSocket::SocketState state)
函数 | 描述 |
---|---|
void setLocalAddress(const QHostAddress &address) | 设置本地 IP 地址。 |
void setLocalPort(quint16 port) | 设置本地端口号。 |
void setPeerAddress(const QHostAddress &address) | 设置对端 IP 地址。 |
void setPeerName(const QString &name) | 设置对端主机名。 |
void setPeerPort(quint16 port) | 设置对端端口号。 |
void setSocketError(QAbstractSocket::SocketError socketError) | 设置套接字的错误状态。 |
void setSocketState(QAbstractSocket::SocketState state) | 设置套接字的状态。 |
2.7 重新实现的保护函数
virtual qint64 readData(char *data, qint64 maxSize) override
virtual qint64 readLineData(char *data, qint64 maxlen) override
virtual qint64 writeData(const char *data, qint64 size) override
这些是 QAbstractSocket 类中的保护成员函数,其作用是重新实现父类的保护成员函数。这些函数包括:
readData():读取数据的函数,用于从 socket 中读取数据,必须在子类中重新实现;
readLineData():读取一行数据的函数,用于从 socket 中读取一行数据,必须在子类中重新实现;
writeData():写入数据的函数,用于向 socket 中写入数据,必须在子类中重新实现。
这些函数是保护成员函数,因此不能在 QAbstractSocket 的对象之外直接调用。而是必须在子类中重新实现,以便实现特定的功能。这些函数通常在 QTcpSocket 或 QUdpSocket 类中重新实现,以实现 TCP 或 UDP 协议的网络通信。