从零开始学Qt(85):TCP通信概述

从零开始学Qt(85):TCP通信概述

TCP是什么?

TCP(Transmission Control Protocol)是一种被大多数Internet网络协议(如HTTP和FTP)用于数据传输的低级网络协议,它是可靠的、面向流、面向连接的传输协议,特别适合用于连续数据传输。

TCP通信必须先建立TCP连接,通信端分为客户端和服务器端。Qt提供 QTcpSocket类和QTcpServer类用于建立TCP通信应用程序。服务器端程序必须使用QTcpServer用于端口监听,建立服务器;QTcpSocket用于建立连接后使用套接字(Socket)进行通信。

从零开始学Qt(85):TCP通信概述

QTcpServer类功能

QTcpServer是从QObject继承的类,它主要用于服务器端建立网络监听,创建网络Socket连接。

QTcpServer类的主要接口函数如下(省略了函数中的const关键字,省略了缺省参数)。

  1. 公共函数
  • void close() 关闭服务器,停止网络监听
  • bool listen() 在给定IP地址和端口上开始监听,若成功就返回true
  • bool isListening() 返回true表明服务器处于监听状态
  • QTcpSocket * nextPendingConnection() 返回下一个等待接入的连接
  • QHostAddress serverAddress() 如果服务器处于监听状态,返回服务器地址
  • quint16 serverPort() 如果服务器处于监听状态,返回服务器监听端口
  • bool waitForNewConnection() 以阻塞方式等待新的连接
  1. 信号
  • void acceptError(QAbstractSocket::SocketError socketError) 当接受一个新的连接发生错误时发射此信号,参数socketError描述了错误信息
  • void newConnection() 当有新的连接时发射此信号
  1. 保护函数
  • void incomingConnection(qintptr socketDescriptor) 当有一个新的连接可用时,QTcpServer内部调用此函数,创建一个QTcpSocket对象,添加到内部可用新连接列表,然后发射newConnection()信号。用户若从QTcpServer继承定义类,可以重定义此函数,但必须调用 addPendingConnection()
  • void addPendingConnection(QTcpSocket * socket) 由incomingConnection()调用,将创建的 QTcpSocket添加到内部新可用连接列表

服务器端程序第一需要用QTcpServer::listen()开始服务器端监听,可以指定监听的IP地址和 端口,一般一个服务程序只监听某个端口的网络连接。

当有新的客户端接入时,QTcpServer内部的incomingConnection()函数会创建一个与客户端连接的QTcpSocket对象,然后发射信号newConnection()。在newConnection()信号的槽函数中,可以用nextPendingConnection()接受客户端的连接,然后使用QTcpSocket与客户端通信。

QTcpSocket类功能

所以在客户端与服务器建立TCP连接后,具体的数据通信是通过QTcpSocket完成的。 QTcpSocket类提供了 TCP协议的接口,可以用QTcpSocket类实现标准的网络通信协议如POP3、SMTP和NNTP,也可以设计自定义协议。

QTcpSocket是从QIODevice间接继承的类,所以具有流读写的功能。QTcpSocket和QUdpSocket的类继承关系如图所示。

从零开始学Qt(85):TCP通信概述

QTcpSocket类除了构造函数和析构函数,其他函数都是从QAbstractSocket继承或重定义的。 QAbstractSocket用于TCP通信的主要接口函数如下 (省略了函数中的const关键字,省略了缺省参数)。

  1. 公共函数
  • void connectToHost(QHostAddress &address, quint16 port) 以异步方式连接到指定IP地址和端口的TCP服务器,连接成功后会发射connected()信号
  • void disconnectFromHost() 断开socket,关闭成功后发射disconnected()信号
  • bool waitForConnected() 等待直到建立socket连接
  • bool waitForDisconnected() 等待直到断开socket连接
  • QHostAddress localAddress() 返回本socket的地址
  • quint16 localPort() 返回本socket的端口
  • QHostAddress peerAddress() 在己连接状态下,返回对方socket的地址
  • QString peerName() 返回connectToHost()连接到的对方的主机名
  • quint16 peerPort() 在己连接状态下,返回对方socket的端口
  • qint64 readBufferSize() 返回内部读取缓冲区的大小,该大小决定了read()和readAll()函数能读出的数据的大小
  • void setReadBufferSize(qint64 size) 设置内部读取缓冲区大小
  • qint64 bytesAvailable() 返回需要读取的缓冲区的数据的字节数
  • bool canReadLine() 如果有行数据要从socket缓冲区读取,就返回true
  • SocketState state() 返回socket当前的状态
  1. 信号
  • void connected() connectToHost()成功连接到服务器后发射此信号
  • void disconnected() 当socket断开连接后发射此信号
  • void error(QAbstractSocket::SocketError socketError) 当socket发生错误时发射此信号
  • void hostFound() 调用connectToHost()找到主机后发射此信号
  • void stateChanged(QAbstractSocket::SocketState socketState) 当socket的状态变化时发射此信号,参数socketState表明了 socket当前的状态
  • void readyRead() 当缓冲区有新数据需要读取时发射此信号,在此信号的槽函数里读取缓冲区的数据

TCP客户端使用QTcpSocket与TCP服务器建立连接并通信。

客户端的QTcpSocket通过connectToHost()尝试连接到服务器,需要指定服务器的IP地址和端口。connectToHost()是异步方式连接服务器,不会阻塞程序运行,连接后发射connected()信号。

如果需要使用阻塞方式连接服务器,则使用waitForConnected()函数阻塞程序运行,直到连接成功或失败。例如:

socket->connectToHost("192.168.1.100", 1340);
if (socket->waitForConnected(1000)) qDebug("Connected!");

与服务器端建立socket连接后,就可以向缓冲区写数据或从接收缓冲区读取数据,实现数据的通信。当缓冲区有新数据进入时,会发射readyRead()信号,一般在此信号的槽函数里读取缓冲区数据。

————————————————

觉得有用的话请关注点赞,谢谢您的支持!

对于本系列文章相关示例完整代码有需要的朋友,可关注并在评论区留言!

© 版权声明

相关文章

2 条评论

您必须登录才能参与评论!
立即登录
  • 头像
    現實世界 读者

    发送端除了回复数据,还要检验是否完整到达,这种方式可以改变一下,由接收端负责这一切,因为接收端又是请求端,严格来说需要负责更多东西

    无记录
  • 头像
    彭康元 读者

    专业

    无记录