注意:本章只有概念概述,主体代码在下一章,完整代码在下面的链接
Qt网络-TCP,实现服务器、客户端传递文本消息和文件(二)
程序图示
1. TCP概述
TCP是可靠的、面向流、面向连接的传输协议,适合用于连续数据传输。
TCP通信必须建立TCP连接,分为客户端和服务端。Qt提供了QTcpSocet和QTcpServer用于建立TCP通信服务。服务段需要使用QTcpServer建立端口监听,QTcpSocket用于连接建立后使用套接字socket进行通信。
注意:TCP连接的四元组:源IP地址、源端口、目的IP地址、目的端口。建立TCP连接时这四个元素要保证至少有一个不同,维持TCP连接的唯一性,不然程序就会出错。
2. QTcpServer类常用函数
void close()
停止监听,关闭服务器
QString errorString() const
返回上次发生的错误
bool isListening() const
返回服务器是否处于监听状态
bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
在给定的IP地址和端口设置监听,成功返回true
virtual QTcpSocket *nextPendingConnection()
返回下一个等待接入的连接
QHostAddress serverAddress() const
如果服务器处于监听状态,返回服务器地址
quint16 serverPort() const
如果服务器处于监听状态,返回服务器监听端口
bool waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR)
以阻塞方式等待新的连接
信号:
void acceptError(QAbstractSocket::SocketError socketError)
当接受一个新的连接发生错误时发送此信号,参数socketError描述了错误信息
void newConnection()
有新的连接时发送此信号
3. QTcpSocket常用函数
virtual void connectToHost(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol)
virtual void connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite)
以异步方式连接到指定IP地址和端口的TCP服务器,连接成功后会发射connected()信号
virtual void disconnectFromHost()
断开socket连接,断开成功后发射disconnected()信号
QHostAddress localAddress() const
返回本socket的地址
quint16 localPort() const
返回本socket的端口
QHostAddress peerAddress() const
在已连接状态下返回对端的socket地址
QString peerName() const
返回由connectToHost()指定的对等方的名称,如果尚未调用connectToHost(),则返回空的QString。
quint16 peerPort() const
在已连接状态下返回对方socket的端口
qint64 readBufferSize() const
返回内部读取缓冲区的大小,该大小决定了read()和readAll()函数能读出的数据大小
virtual void setReadBufferSize(qint64 size)
设置内部读取缓冲区大小
virtual qint64 bytesAvailable() const
返回需要读取的缓冲区数据的字节数
virtual bool canReadLine() const
如果有行数据要从socket缓冲区读取,返回true
SocketState state() const
返回当前socket状态
virtual bool waitForConnected(int msecs = 30000)
等待直到建立socket连接
virtual bool waitForDisconnected(int msecs = 30000)
等待直到断开socket连接
信号:
void connected()
调用connectToHost()连接成功时发射此信号
void disconnected()
断开socket连接时发射此信号
void error(QAbstractSocket::SocketError socketError)
socket发生错误时发射此信号,可以连接自定义槽函数捕获错误详情
void hostFound()
调用connectToHost()找到主机后发射此信号
void stateChanged(QAbstractSocket::SocketState socketState)
socket状态变化时发射此信号。
void readyRead()
当缓冲区由新数据需要读取时发射此信号,参数表示socket当前状态
void bytesWritten(qint64 bytes)
每次将有效数据写入设备的当前写入通道时,都会发出此信号。bytes参数设置为写入的字节数。
4. 工作流程
服务器使用listen开启监听,指定监听的地址和端口,一般一个服务程序只监听某一个端口的网络连接。
有新的客户端接入时,QTcpServer内部的incomingConnection()函数会创建一个与客户端连接的QTcpSocket对象,然后发射信号newConnection()。在newConnection()槽函数中,可以用nextPendingConnection()接受客户端的连接,然后与客户端通信。客户端与服务器连接建立后通过QTcpSocket完成数据通信。
客户端的QTcpSocket实例通过connectToHost尝试连接到服务器,需要指定服务器的IP地址和端口。connectToHost是异步方式连接服务器,不会阻塞程序运行。
需要阻塞的话,在connectToHost后使用waitForConnected()等待连接。
连接建立后,可以向缓冲区写入数据或从缓冲区读数据,实现数据通信。当缓冲区有数据写入时,会发射readyRead()信号,一般在此信号的槽函数中读取数据。
一个QTcpSocket实例既可以接收数据也可以发送数据,且接收与发送是异步工作的,有各自的缓冲区。