网络通讯【QTcpServer、QTcpSocket、QAbstractSocket】
目录
- QTcpServer class
- 简单描述
- 成员函数和信号
- QTcpSocket Class
- 详细描述
- 成员函数和信号
- QAbstractSocket Class
- 详细描述
- 成员函数和信号
- 成员函数说明文档
- QT实现服务器和客户端通讯
- 服务器端:
- 通讯流程
- 原代码
- 客户端
- 通信流程
- 原代码
QTcpServer class
header:
#include <QTcpSocket>
Cmake:
find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake:
QT += network
简单描述
该类继承QObject,允许接受传入的TCP连接。可以指定端口,也可以让QTcpServer自动选择一个端口。监听特定地址或所有机器地址。
调用listen()
让服务器侦听传入的连接。每次客户端连接到服务器时,服务器会发出newConnection()
信号。当使用addPendingConnection()
函数将客户端连接添加到挂起的连接队列时,pendingConnectionAvailable()
信号会被发出。
调用nextPendingConnection()
以接受挂起的连接作为已连接的QTcpSocket。该函数返回指向QAbstractSocket::ConnectedState中QTcpSocket的指针,可用于与客户端通信。如果发生错误,serverError()
将返回错误类型,并且可以调用errorString()
来获得所发生事情的可读描述。
在侦听连接时,服务器正在侦听的地址和端口可用作serverAddress()
和serverPort()
。调用close()
将使QTcpServer停止侦听传入连接。尽管QTcpServer主要是为与事件循环一起使用而设计的,但也可以在没有事件循环的情况下使用它。在这种情况下,您必须使用waitForNewConnection()
,它会阻塞直到连接可用或超时。
成员函数和信号
//signal
void QTcpServer::acceptError(QAbstractSocket::SocketError socketError)
//当接受新连接导致错误时,会发出此信号。socketError参数描述了发生的错误类型。
void QTcpServer::newConnection()
//每当有新的连接可用时,无论它是否已添加到挂起的连接队列中,都会发出此信号。
void QTcpServer::pendingConnectionAvailable()
//每当向挂起的连接队列中添加新连接时,就会发出此信号。//public functions
void QTcpServer::close()
//关闭服务器。服务器将不再侦听传入连接
QString QTcpServer::errorString() const
//返回上次发生的错误的可读说明。
bool QTcpServer::hasPendingConnections() const
//如果服务器有挂起的连接,则返回true;否则返回false。
bool QTcpServer::isListening() const
//如果服务器当前正在侦听传入连接,则返回true;否则返回false。
bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
//告诉服务器侦听地址地址和端口端口上的传入连接。如果端口为0,则会自动选择端口。如果地址为QHostAddress::Any,则服务器将侦听所有网络接口。
//成功时返回true;否则返回false。
int QTcpServer::listenBacklogSize() const
//返回要接受的连接的积压工作队列大小。
int QTcpServer::maxPendingConnections() const
//返回挂起的可接受连接的最大数目。默认值为30。
QTcpSocket *QTcpServer::nextPendingConnection()
//将下一个挂起的连接作为已连接的QTcpSocket对象返回。
//套接字是作为服务器的子级创建的,这意味着当QTcpServer对象被破坏时,它会被自动删除。在处理完对象后,显式删除该对象仍然是一个好主意,以避免浪费内存。
//如果在没有挂起的连接时调用此函数,则返回nullptr。
void QTcpServer::pauseAccepting()
//暂停接受新连接。排队的连接将保留在队列中。
QNetworkProxy QTcpServer::proxy() const
//返回此套接字的网络代理。默认情况下,使用QNetworkProxy::DefaultProxy。
void QTcpServer::resumeAccepting()
//继续接受新连接。
QHostAddress QTcpServer::serverAddress() const
//如果服务器正在侦听连接,则返回服务器的地址;否则返回QHostAddress::Null。
QAbstractSocket::SocketError QTcpServer::serverError() const
//返回上次发生的错误的错误代码。
quint16 QTcpServer::serverPort() const
//如果服务器正在侦听连接,则返回服务器的端口;否则返回0。
void QTcpServer::setListenBacklogSize(int size)
//将要接受的连接的囤积队列大小设置为大小。操作系统可能会减少或忽略此值。默认情况下,队列大小为50。
void QTcpServer::setMaxPendingConnections(int numConnections)
//将挂起的可接受连接的最大数量设置为numConnections。在调用nextPendingConnection()之前,QTcpServer将接受不超过numConnections的传入连接。默认情况下,限制为30个挂起的连接。
//在服务器达到其挂起连接的最大数量后,客户端仍然可以连接(即,QTcpSocket仍然可以发出connected()信号)。QTcpServer将停止接受新连接,但操作系统可能仍会将它们保留在队列中。
void QTcpServer::setProxy(const QNetworkProxy &networkProxy)
//将此套接字的显式网络代理设置为networkProxy。
bool QTcpServer::setSocketDescriptor(qintptr socketDescriptor)
//设置此服务器在侦听到socketDescriptor的传入连接时应使用的套接字描述符。如果套接字设置成功,则返回true;否则返回false。
qintptr QTcpServer::socketDescriptor() const
//返回服务器用于侦听传入指令的本机套接字描述符,如果服务器未在侦听,则返回-1。
//如果服务器使用QNetworkProxy,则返回的描述符可能无法与本机套接字函数一起使用。
bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = nullptr)
//最多等待毫秒,或者直到传入连接可用。如果连接可用,则返回true;否则返回false。如果操作超时并且timedOut不是nullptr,则*timedOut将设置为true。
//这是一个阻塞函数调用。它在单线程GUI应用程序中的使用是不利的,因为整个应用程序将停止响应,直到函数返回。waitForNewConnection()在没有可用的事件循环时非常有用。
//非阻塞的替代方法是连接到newConnection()信号。
//如果毫秒为-1,则此功能不会超时。//protected function
void QTcpServer::addPendingConnection(QTcpSocket *socket)
//此函数由QTcpServer::incomingConnection()调用,用于将套接字添加到挂起的传入连接列表中。
void QTcpServer::incomingConnection(qintptr socketDescriptor)
//当新连接可用时,QTcpServer会调用此虚拟函数。socketDescriptor参数是接受连接的本机套接字描述符。
//基本实现创建一个QTcpSocket,设置套接字描述符,然后将QTcpSockets存储在挂起连接的内部列表中。最后发出newConnection()。
//当连接可用时,重新实现此函数以更改服务器的行为。
//如果此服务器使用QNetworkProxy,则socketDescriptor可能无法与本机套接字函数一起使用,而只能与QTcpSocket::setSocketDescriptor()一起使用。
QTcpSocket Class
#include <QTcpSocket>
CMake: find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake: QT += network
详细描述
TCP(传输控制协议)是一种可靠的、面向流的、面向连接的传输协议。它特别适合连续传输数据。
QTcpSocket是QAbstractSocket的一个子类,它允许您建立TCP连接和传输数据流。
成员函数和信号
QTcpSocket::QTcpSocket(QObject *parent = nullptr)
//创建状态为UnconnectedState的QTcpSocket对象。
//父对象被传递给QObject构造函数。
QTcpSocket::~QTcpSocket()
//销毁套接字,必要时关闭连接。
QAbstractSocket Class
#include <QAbstractSocket>
CMake:
find_package(Qt6 REQUIRED COMPONENTS Network)
find_package(Qt6 REQUIRED COMPONENTS Network)target_link_libraries(mytarget PRIVATE Qt6::Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake: QT += network
详细描述
QAbstractSocket是QTcpSocket和QUdpSocket的基类,包含这两个类的所有通用功能。如果你需要一个套接字,你有两个选择:1、实例化QTcpSocket
或QUdpSocket
;2、创建一个本机套接字描述符,实例化QAbstractSocket
,并调用setSocketDescriptor()
来包装本机套接字。
TCP(传输控制协议)是一种可靠的、面向流的、面向连接的传输协议。UDP(用户数据报协议)是一种不可靠的、面向数据报的、无连接的协议。在实践中,TCP更适合于数据的连续传输,而当可靠性不重要时,可以使用更轻量级的UDP。
socket的API统一了这两个协议之间的大部分差异。例如,尽管UDP是无连接的,但connectToHost()
为UDP套接字建立了一个虚拟连接,使您能够以或多或少相同的方式使用QAbstractSocket,而不考虑底层协议。在内部,QAbstractSocket记住传递给connectToHost()
的地址和端口,像read()
和write()
这样的函数使用这些值。
在任何时候,QAbstractSocket都有一个状态(由state()返回)。初始状态为UnconnectedState。调用connectToHost()
后,套接字首先进入HostLookupState。如果找到主机,QAbstractSocket进入ConnectingState并发出hostFound()
信号。当连接建立后,它进入ConnectedState并发出connected()
。如果在任何阶段发生错误,则会触发errorOccurred()
。每当状态发生变化时,就会触发stateChanged()
。为方便起见,isValid()
返回 true 如果套接字已经准备好读写,但注意,在读写之前,套接字的状态必须是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() 阻塞,直到连接关闭。
使用阻塞套接字进行编程与使用非阻塞套接字进行编程完全不同。阻塞套接字不需要事件循环,通常会导致更简单的代码。
成员函数和信号
enum QAbstractSocket::BindFlag ,flags QAbstractSocket::BindMode
描述了可以传递的不同标志,以修改QAbstractSocket::bind()的行为。
Column 1 | Column 2 | Column 1 |
---|---|---|
QAbstractSocket::ShareAddress | 0x1 | 允许其他服务绑定到相同的地址和端口。当多个进程通过侦听相同的地址和端口来共享单个服务的负载时,这是有用的(例如,具有多个预分叉侦听器的web服务器可以大大提高响应时间)。但是,由于任何服务都允许重新绑定,因此此选项需要考虑某些安全因素。请注意,通过将此选项与ReuseAddressHint组合,您还将允许您的服务重新绑定现有的共享地址。在Unix上,这相当于SO_REUSEADDR套接字选项。在Windows上,这是默认行为,因此忽略此选项。 |
QAbstractSocket::DontShareAddress | 0x2 | 只绑定地址和端口,不允许其他服务重新绑定。通过将此选项传递给QAbstractSocket::bind(),您可以保证在成功时,您的服务是唯一侦听地址和端口的服务。任何服务都不允许重新绑定,即使它们传递了ReuseAddressHint。此选项提供了比ShareAddress更高的安全性,但在某些操作系统上,它要求您以管理员权限运行服务器。在Unix和macOS上,不共享是绑定地址和端口的默认行为,因此忽略此选项。在Windows上,该选项使用SO_EXCLUSIVEADDRUSE套接字选项。 |
QAbstractSocket::ReuseAddressHint | 0x4 | 向QAbstractSocket提供提示,提示它应该尝试重新绑定服务,即使地址和端口已经被另一个套接字绑定。在Windows和Unix上,这相当于SO_REUSEADDR套接字选项。 |
QAbstractSocket::DefaultForPlatform | 0x0 | 当前平台的默认选项。在Unix和macOS上,这相当于(DontShareAddress ReuseAddressHint),在Windows上,它相当于ShareAddress。 |
enum QAbstractSocket::NetworkLayerProtocol
描述Qt中使用的网络层协议值。
constant | value | Description |
---|---|---|
QAbstractSocket::IPv4Protocol | 0 | IPv4 |
QAbstractSocket::IPv6Protocol | 1 | IPv6 |
QAbstractSocket::AnyIPProtocol | 2 | 支持IPv4或IPv6 |
QAbstractSocket::UnknownNetworkLayerProtocol | -1 | 除了IPv4和IPv6 |
enum QAbstractSocket::PauseMode
描述套接字在继续传输数据时应该保留的行为。目前唯一支持的通知是QSslSocket::sslErrors()。
constant | value | Description |
---|---|---|
QAbstractSocket::PauseNever | 0x0 | 不要暂停套接字上的数据传输。这是默认的,并且与Qt 4的行为相匹配。 |
QAbstractSocket::PauseOnSslErrors | 0x1 | 在收到SSL错误通知时,暂停套接字上的数据传输。即QSslSocket: sslErrors()。 |
PauseModes类型是QFlags的类型定义。它存储一个或组合的PauseMode值。
enum QAbstractSocket::SocketError
描述可能发生的套接字错误。
constant | value | Description |
---|---|---|
QAbstractSocket::ConnectionRefusedError | 0 | 连接被对等端拒绝(或超时)。 |
QAbstractSocket::RemoteHostClosedError | 1 | 远程主机关闭了连接。请注意,客户端套接字(即这个套接字)将在发送远程关闭通知后关闭。 |
QAbstractSocket::HostNotFoundError | 2 | 找不到主机地址。 |
QAbstractSocket::SocketAccessError | 3 | 由于应用程序缺乏所需的权限,套接字操作失败。 |
QAbstractSocket::SocketResourceError | 4 | 本地系统资源耗尽(例如,套接字太多)。 |
QAbstractSocket::SocketTimeoutError | 5 | socket操作超时。 |
QAbstractSocket::DatagramTooLargeError | 6 | 数据报大于操作系统的限制(可以低至8192字节)。 |
QAbstractSocket::NetworkError | 7 | 网络发生错误(例如,意外拔出网线)。 |
QAbstractSocket::AddressInUseError | 8 | 指定给QAbstractSocket::bind()的地址已经在使用,并且被设置为排他的。 |
QAbstractSocket::SocketAddressNotAvailableError | 9 | 指定给QAbstractSocket::bind()的地址不属于主机。 |
QAbstractSocket::UnsupportedSocketOperationError | 10 | 本地操作系统不支持请求的套接字操作(例如,缺乏IPv6支持)。 |
QAbstractSocket::ProxyAuthenticationRequiredError | 12 | 套接字正在使用代理,代理需要身份验证。 |
QAbstractSocket::SslHandshakeFailedError | 13 | SSL/TLS握手失败,因此连接被关闭(仅在QSslSocket中使用) |
QAbstractSocket::UnfinishedSocketOperationError | 11 | 仅由QAbstractSocketEngine使用,最后尝试的操作尚未完成(仍在后台进行中)。 |
QAbstractSocket::ProxyConnectionRefusedError | 14 | 无法联系代理服务器,因为与该服务器的连接被拒绝 |
QAbstractSocket::ProxyConnectionClosedError | 15 | 与代理服务器的连接被意外关闭(在与最终对等端建立连接之前) |
QAbstractSocket::ProxyConnectionTimeoutError | 16 | 代理服务器连接超时或认证阶段代理服务器停止响应。处理步骤 |
QAbstractSocket::ProxyNotFoundError | 17 | 找不到使用setProxy()(或应用程序代理)的代理地址集。 |
QAbstractSocket::ProxyProtocolError | 18 | 与代理服务器的连接协商失败,因为无法理解来自代理服务器的响应。 |
QAbstractSocket::OperationError | 19 | 当套接字处于不允许的状态时,尝试进行操作。 |
QAbstractSocket::SslInternalError | 20 | 正在使用的SSL库报告了内部错误。这可能是错误安装或错误配置库的结果。 |
QAbstractSocket::SslInvalidUserDataError | 21 | 提供了无效数据(证书、密钥、密码等),其使用导致SSL库中出现错误。 |
QAbstractSocket::TemporaryError | 22 | 发生临时错误(例如,操作将阻塞而套接字未阻塞)。 |
QAbstractSocket::UnknownSocketError | -1 | 发生了一个无法识别的错误 |
enum QAbstractSocket::SocketOption
表示可在套接字上设置的选项。如果需要,可以在从套接字接收到connected()信号或从QTcpServer接收到新的套接字之后设置它们。
constant | value | Description |
---|---|---|
QAbstractSocket::LowDelayOption | 0 | 尝试优化套接字以实现低延迟。对于QTcpSocket,这将设置TCP_NODELAY选项并禁用Nagle算法。将此设置为1以启用。 |
QAbstractSocket::KeepAliveOption | 1 | 将其设置为1以启用SO_KEEPALIVE套接字选项 |
QAbstractSocket::SocketAccessError | 2 | 将此值设置为整数,以设置IP_MULTICAST_TTL(组播数据报的TTL)套接字选项。 |
QAbstractSocket::MulticastLoopbackOption | 3 | 将此值设置为1将启用IP_MULTICAST_LOOP(组播环回)套接字选项。 |
QAbstractSocket::TypeOfServiceOption | 4 | Windows不支持此选项。这映射到IP_TOS套接字选项。有关可能的值,请参见下表。 |
QAbstractSocket::SendBufferSizeSocketOption | 5 | 在操作系统级别以字节为单位设置套接字发送缓冲区大小。这映射到SO_SNDBUF套接字选项。此选项不影响QIODevice或QAbstractSocket缓冲区。 |
QAbstractSocket::ReceiveBufferSizeSocketOption | 6 | 在操作系统级别以字节为单位设置套接字接收缓冲区大小。这映射到SO_RCVBUF套接字选项。 |
QAbstractSocket::PathMtuSocketOption | 7 | 获取IP栈当前已知的路径最大传输单元(PMTU)值(如果有)。一些IP栈也允许设置传输的MTU。 |
enum QAbstractSocket::SocketState
描述套接字可以处于的不同状态
constant | value | Description |
---|---|---|
QAbstractSocket::UnconnectedState | 0 | 套接字未连接。 |
QAbstractSocket::HostLookupState | 1 | 套接字正在执行主机名查找。 |
QAbstractSocket::ConnectingState | 2 | 套接字已开始建立连接。 |
QAbstractSocket::ConnectedState | 3 | 连接建立。 |
QAbstractSocket::BoundState | 4 | 套接字绑定到一个地址和端口。 |
QAbstractSocket::ClosingState | 6 | 套接字即将关闭(数据可能仍在等待写入)。 |
QAbstractSocket::ListeningState | 5 | 仅供内部使用。 |
enum QAbstractSocket::SocketType
描述传输层协议。
constant | value | Description |
---|---|---|
QAbstractSocket::TcpSocket | 0 | TCP |
QAbstractSocket::UdpSocket | 1 | UDP |
QAbstractSocket::SctpSocket | 2 | SCTP |
QAbstractSocket::UnknownSocketType | -1 | 除了TCP、UDP和SCTP |
成员函数说明文档
Public Function
QAbstractSocket::QAbstractSocket(QAbstractSocket::SocketType socketType, QObject *parent)
//类型的新抽象套接字。参数被传递给QObject的构造函数。
QAbstractSocket::~QAbstractSocket()
//销毁套接字
void QAbstractSocket::abort()
//中止当前连接并重置套接字。与disconnectFromHost()不同,此函数会立即关闭套接字,丢弃写缓冲区中任何挂起的数据。
bool QAbstractSocket::bind(const QHostAddress &address, quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)
//使用BindMode绑定到端口。
//对于UDP套接字,在绑定之后,只要UDP数据报到达指定的地址和端口,就会发出信号QUdpSocket::readyRead()。因此,该函数对于编写UDP服务器非常有用。
//对于TCP套接字,此函数可用于指定用于传出连接的接口,这在多个网络接口的情况下很有用。
//缺省情况下,使用DefaultForPlatform BindMode绑定套接字。如果不指定端口,系统将随机选择端口。
//如果调用成功,返回 true , socket进入BoundState状态;否则返回 false 。
bool QAbstractSocket::bind(QHostAddress::SpecialAddress addr, quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)
//使用BindMode绑定到端口上的特殊地址。这是一个重载函数。
//缺省情况下,使用DefaultForPlatform BindMode绑定套接字。如果不指定端口,系统将随机选择端口。Qt 6.2中引入的
bool QAbstractSocket::bind(quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)
//绑定到QHostAddress:任何端口,使用BindMode。
//缺省情况下,使用DefaultForPlatform BindMode绑定套接字。如果不指定端口,系统将随机选择端口。
void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, QIODeviceBase::OpenMode openMode = ReadWrite, QAbstractSocket::NetworkLayerProtocol protocol = AnyIPProtocol)
//试图建立一个连接到给定的。该参数可用于指定使用哪种网络协议(例如。IPv4或IPv6)。
//套接字在给定的条件下打开,首先进入HostLookupState,然后执行主机名查找。如果查找成功,则发出hostFound(), QAbstractSocket进入ConnectingState。然后,它尝试连接到查找返回的地址或地址。最后,如果建立了连接,QAbstractSocket将进入ConnectedState并发出connected()。
//在任何时候,套接字都可以发出errorOccurred()来表示发生了错误。
//可以是字符串形式的IP地址(例如,“43.195.83.32”),也可以是主机名(例如,“example.com”)。QAbstractSocket只在需要时进行查找。是本机字节顺序。
void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, QIODeviceBase::OpenMode openMode = ReadWrite)
//这是一个重载函数。试图连接到某个端口。
void QAbstractSocket::disconnectFromHost()
//试图关闭套接字。如果有挂起的数据等待写入,QAbstractSocket将进入ClosingState并等待,直到所有数据都被写入。最终,它将进入UnconnectedState并发出disconnected()信号。
bool QAbstractSocket::flush()
//此函数将尽可能多地从内部写缓冲区写入底层网络套接字,而不会阻塞。如果有数据写入,这个函数返回 true ;否则返回false。
bool QAbstractSocket::isValid() const
//如果套接字有效且可以使用,则返回 true ;否则返回 false 。
QHostAddress QAbstractSocket::localAddress() const
//如果可用,返回本地套接字的主机地址;否则返回QHostAddress::Null。
//这通常是主机的主IP地址,但也可以是QHostAddress::LocalHost(127.0.0.1),用于连接到本地主机。
quint16 QAbstractSocket::localPort() const
//如果可用,返回本地套接字的主机端口号(以本机字节顺序);否则返回0。
QAbstractSocket::PauseModes QAbstractSocket::pauseMode() const
//返回此套接字的暂停模式。
QHostAddress QAbstractSocket::peerAddress() const
//如果套接字处于ConnectedState状态,则返回被连接对等体的地址;否则返回QHostAddress::Null。
QString QAbstractSocket::peerName() const
//返回connectToHost()指定的对端名称,如果connectToHost()未被调用,则返回空QString。
quint16 QAbstractSocket::peerPort() const
//如果套接字处于ConnectedState状态,则返回被连接对等体的端口;否则返回0。
QString QAbstractSocket::protocolTag() const
//返回此套接字的协议标记。如果设置了协议标签,则在内部创建QNetworkProxyQuery时将其传递给QNetworkProxyQuery,以指示要使用的协议标签。
QNetworkProxy QAbstractSocket::proxy() const
//返回此套接字的网络代理。默认情况下使用QNetworkProxy::DefaultProxy,这意味着这个套接字将查询应用程序的默认代理设置。
qint64 QAbstractSocket::readBufferSize() const
//返回内部读缓冲区的大小。这限制了客户机在调用read()或readAll()之前可以接收的数据量。
//读缓冲区大小为0(默认值)意味着缓冲区没有大小限制,确保没有数据丢失。
void QAbstractSocket::resume()
//继续在套接字上传输数据。此方法只应在套接字被设置为在收到通知时暂停并且收到通知后使用。目前唯一支持的通知是QSslSocket::sslErrors()。如果套接字未暂停,则调用此方法将导致未定义的行为。
void QAbstractSocket::setPauseMode(QAbstractSocket::PauseModes pauseMode)
//控制是否在收到通知时暂停。该参数指定套接字暂停的条件。目前唯一支持的通知是QSslSocket::sslErrors()。如果设置为PauseOnSslErrors,则套接字上的数据传输将被暂停,需要通过调用resume()再次显式启用。默认情况下,此选项被设置为PauseNever。此选项必须在连接到服务器之前调用,否则将导致未定义的行为。
QAbstractSocket::setProtocolTag(const QString &)
//设置此套接字的协议标记
void QAbstractSocket::setProxy(const QNetworkProxy &networkProxy)
//设置套接字的显式网络代理
socket->setProxy(QNetworkProxy::NoProxy);//禁用此套接字的代理
void QAbstractSocket::setReadBufferSize(qint64 size)
//将QAbstractSocket的内部读缓冲区的大小设置为字节。
bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = ConnectedState, QIODeviceBase::OpenMode openMode = ReadWrite)
//用本机套接字描述符初始化QAbstractSocket。如果接受为有效的套接字描述符,则返回 true ;否则返回 false 。套接字按照指定的模式打开,进入指定的套接字状态。读取和写入缓冲区被清除,丢弃任何挂起的数据。
void QAbstractSocket::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
//设置给定的值
qintptr QAbstractSocket::socketDescriptor() const
//返回QAbstractSocket对象的本机套接字描述符(如果可用);否则返回-1。
QVariant QAbstractSocket::socketOption(QAbstractSocket::SocketOption option)
//返回选项的值。
QAbstractSocket::SocketType QAbstractSocket::socketType() const
//返回套接字类型(TCP、UDP或其他)。
QAbstractSocket::SocketState QAbstractSocket::state() const
//返回套接字的状态。
bool QAbstractSocket::waitForConnected(int msecs = 30000)
//等待,直到套接字连接,最多毫秒。如果连接已经建立,这个函数返回 true ;否则返回 false 。在返回 false 的情况下,可以调用error()来确定错误的原因。
bool QAbstractSocket::waitForDisconnected(int msecs = 30000)
//等待,直到套接字已断开连接,最多毫秒。如果连接已成功断开,此函数返回 true ;否则,它返回 false (如果操作超时,如果发生错误,或者如果这个QAbstractSocket已经断开连接)。在返回 false 的情况下,可以调用error()来确定错误的原因。
Reimplemented Public Functions**//重载公共函数**
qint64 QAbstractSocket::bytesAvailable() const
//重构:QIODevice::bytesAvailable() const。,返回等待读取的传入字节数。
qint64 QAbstractSocket::bytesToWrite() const
//重构:QIODevice:: bytestosterone () const。返回等待写入的字节数。当控制返回事件循环或调用flush()时写入字节。
void QAbstractSocket::close()
//重构:QIODevice:: close()。关闭套接字的I/O设备,并调用disconnectFromHost()来关闭套接字的连接。
bool QAbstractSocket::isSequential() const
//重载:QIODevice::isSequential() const。
bool QAbstractSocket::waitForBytesWritten(int msecs = 30000)
//重新实现:QIODevice::waitForBytesWritten(int msecs)。该函数会阻塞,直到至少有一个字节被写入套接字并发出bytesWritten()信号。该函数将在毫秒后超时;默认超时时间为30000毫秒。如果发出bytesWritten()信号,该函数返回 true ;否则返回 false (如果发生错误或操作超时)。
bool QAbstractSocket::waitForReadyRead(int msecs = 30000)
//重新实现:QIODevice::waitForReadyRead(int msecs)。
//这个函数会阻塞,直到有新的数据可供读取,并且发出readyRead()信号。该函数将在毫秒后超时;默认超时时间为30000毫秒。
signal:
void QAbstractSocket::connected()
//这个信号在connectToHost()被调用并且连接已经成功建立之后发出。
void QAbstractSocket::disconnected()
//该信号在套接字断开连接时发出。
void QAbstractSocket::errorOccurred(QAbstractSocket::SocketError socketError)
//此信号在发生错误后发出。该参数描述发生的错误类型。
//当发出此信号时,套接字可能尚未准备好进行重新连接尝试。在这种情况下,应该从事件循环尝试重新连接。例如,使用QTimer::singleShot()将超时设置为0。
//QAbstractSocket::SocketError不是已注册的元类型,因此对于排队的连接,您必须使用Q_DECLARE_METATYPE()和qRegisterMetaType()来注册它。
void QAbstractSocket::hostFound()
//这个信号在connectToHost()被调用并且主机查找成功后发出。
void QAbstractSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)
//当使用需要身份验证的a时,可以发出此信号。然后可以用所需的详细信息填充对象,以允许身份验证并继续连接。
void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)
//每当QAbstractSocket的状态发生变化时,就会发出这个信号。该参数为新状态。
protected Fuctions
void QAbstractSocket::setLocalAddress(const QHostAddress &)
//将连接的本地端的地址设置为。
//您可以在QAbstractSocket的子类中调用此函数,以便在建立连接后更改localAddress()函数的返回值。代理连接通常使用此功能进行虚拟连接设置。
//注意,此函数在连接之前不绑定套接字的本地地址(例如,QAbstractSocket::bind())。
void QAbstractSocket::setLocalPort(quint16)
//将连接的本地端端口设置为。
//您可以在QAbstractSocket的子类中调用此函数,以便在建立连接后更改localPort()函数的返回值。代理连接通常使用此功能进行虚拟连接设置。
//注意,此函数在连接之前不绑定套接字的本地端口(例如,QAbstractSocket::bind())。
void QAbstractSocket::setPeerAddress(const QHostAddress &address)
//将连接的远端地址设置为。
//您可以在QAbstractSocket的子类中调用此函数,以便在建立连接后更改peerAddress()函数的返回值。代理连接通常使用此功能进行虚拟连接设置。
void QAbstractSocket::setPeerName(const QString &name)
//设置远程对等体的主机名
void QAbstractSocket::setPeerPort(quint16 port)
//设置连接的远程端口号
void QAbstractSocket::setSocketError(QAbstractSocket::SocketError socketError)
//设置上次发生的错误类型
void QAbstractSocket::setSocketState(QAbstractSocket::SocketState state)
//设置套接字的状态
Reimplemented Protected Functions**//重新实现保护函数**
qint64 QAbstractSocket::readData(char *, qint64)
//重新实现:QIODevice::readData(char *data, qint64 maxSize)。
qint64 QAbstractSocket::readLineData(char *, qint64)
//重新实现:QIODevice::readLineData(char *data, qint64 maxSize)
qint64 QAbstractSocket::writeData(const char *data, qint64 size)
//重新实现:QIODevice::writeData(const char *data, qint64 maxSize)。
qint64 QAbstractSocket::skipData(qint64 maxSize)
//重新实现:QIODevice::skipData(qint64 maxSize).
补充一个
void QIODevice::readyRead()
//每当从设备当前读取通道中读取新数据时,该信号就会发出一次。它只会在有新数据可用时再次发出,例如当新的网络数据负载到达您的网络套接字时,或者当一个新的数据块被附加到您的设备时。
//readyRead()不是递归触发的;如果您重新进入事件循环或在连接到readyRead()信号的插槽中调用waitForReadyRead(),则信号将不会被重新发出(尽管waitForReadyRead()可能仍然返回true)。
//对于实现从QIODevice派生类的开发人员,请注意:当新数据到达时,您应该总是发出readyRead()(不要仅仅因为缓冲区中仍有数据要读取而发出)。不要在其他情况下发出readyRead()。
QT实现服务器和客户端通讯
服务器端:
通讯流程
1、创建套接字服务器QTcpserver对象。
2、通过QTcpServer对象设置监听,即:QTcpServer::listen()。
3、基于QTcpServer::newConnection()信号检测是否有新的客户端连接。
4、如果有新的客户端连接调用QTcpSocket *QTcpServer::nextPendingConnection()得到通信的套接字对象。
5、使用通信套接字对象QTcpSocket 和客户端进行通信
原代码
mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QTcpSocket>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->lineEdit_port->setText("8899");setWindowTitle("服务器");//创建监听服务器对象m_s = new QTcpServer(this);connect(m_s,&QTcpServer::newConnection,this,[=](){//通讯套接字对象m_tcp = m_s->nextPendingConnection();m_label->setPixmap(QPixmap(":/connect1.jpg").scaled(20,20));//检测是否可以接收数据connect(m_tcp,&QTcpSocket::readyRead,this,[=](){QByteArray data = m_tcp->readAll();ui->textEdit_log->append("客户端say:"+data);});connect(m_tcp,&QTcpSocket::disconnected,this,[=](){m_tcp->close();m_tcp->deleteLater();m_label->setPixmap(QPixmap(":/unconnect1.jpg").scaled(20,20));ui->pushButton_listen->setDisabled(false);m_s->close();});});//状态栏m_label = new QLabel;m_label->setPixmap(QPixmap(":/unconnect1.jpg").scaled(20,20));ui->statusbar->addWidget(new QLabel("连接状态:"));ui->statusbar->addWidget(m_label);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_listen_clicked()
{unsigned short port = ui->lineEdit_port->text().toUShort();m_s->listen(QHostAddress::Any,port);ui->pushButton_listen->setDisabled(true);}void MainWindow::on_pushButtonsend_clicked()
{QString msg = ui->textEdit_send->toPlainText();m_tcp->write(msg.toUtf8());ui->textEdit_log->append("服务器say:" + msg);ui->textEdit_send->clear();}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QLabel>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_listen_clicked();void on_pushButtonsend_clicked();private:Ui::MainWindow *ui;QTcpServer *m_s;QTcpSocket *m_tcp;QLabel *m_label;
};
#endif // MAINWINDOW_H
服务器UIj界面:
客户端
通信流程
1、创建套接字QTcpSocket对象。
2、使用服务器端绑定的IP和端口连接服务器QAbstractSocket::connectToHost()。
3、使用QTcpSocket对象和服务器进行通讯。
原代码
mainwidow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"#include <QTcpSocket>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->lineEdit_port->setText("8899");ui->lineEdit_IP->setText("127.0.0.1");setWindowTitle("客户端");ui->pushButton_disconnect->setDisabled(true);//创建监听服务器对象m_tcp = new QTcpSocket;connect(m_tcp,&QTcpSocket::readyRead,this,[=](){QByteArray data = m_tcp->readAll();ui->textEdit_log->append("服务器say:"+data);});connect(m_tcp,&QTcpSocket::disconnected,this,[=](){m_tcp->close();//tcp断开
// m_tcp->deleteLater();//内存资源释放m_label->setPixmap(QPixmap(":/unconnect1.jpg").scaled(20,20));ui->textEdit_log->append("断开连接服务器.....");ui->pushButton_connect->setDisabled(false);ui->pushButton_disconnect->setEnabled(false);});connect(m_tcp,&QTcpSocket::connected,this,[=](){m_label->setPixmap(QPixmap(":/connect1.jpg").scaled(20,20));ui->textEdit_log->append("成功连接服务器.....");ui->pushButton_connect->setDisabled(true);ui->pushButton_disconnect->setEnabled(true);});//状态栏m_label = new QLabel;m_label->setPixmap(QPixmap(":/unconnect1.jpg").scaled(20,20));ui->statusbar->addWidget(new QLabel("连接状态:"));ui->statusbar->addWidget(m_label);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButtonsend_clicked()
{QString msg = ui->textEdit_send->toPlainText();m_tcp->write(msg.toUtf8());ui->textEdit_log->append("客户端say:" + msg);ui->textEdit_send->clear();}void MainWindow::on_pushButton_connect_clicked()
{QString ip = ui->lineEdit_IP->text();unsigned short port = ui->lineEdit_port->text().toUShort();m_tcp->connectToHost(QHostAddress(ip),port);}void MainWindow::on_pushButton_disconnect_clicked()
{m_tcp->close();ui->pushButton_connect->setDisabled(false);ui->pushButton_disconnect->setEnabled(false);
}
mainwidow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>#include <QTcpSocket>
#include <QLabel>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButtonsend_clicked();void on_pushButton_connect_clicked();void on_pushButton_disconnect_clicked();private:Ui::MainWindow *ui;QTcpSocket *m_tcp;QLabel *m_label;
};
#endif // MAINWINDOW_H
UI界面:
参考:
csdn:https://blog.csdn.net/qq_43689451/article/details/145674555
B站:https://www.bilibili.com/video/BV1LB4y1F7P7?