一、TCP特点

  • 是可靠的、面向流、面向连接饿传输协议,适合用于连续数据传输


三次握手

服务端和客户端建立稳定的传输通道,需要3个步骤

  1. 客户端向服务器发送信息,发送一个报文(syn(请求同步))
  2. 服务端将受到的客户端的报文重新发回去,再多加一个报文(ack(确认))
  3. 客户端再向服务端发送报文(ack)

四次挥手

服务端和客户端断开传输通断,需要4个步骤

  1. 客户端向服务端发送报文(fin(结束标志))
  2. 服务端收到这个报文,它回复一个报文(ack)
  3. 服务端关闭客户端连接
  4. 客户端发挥(ack)报文确认



TCP通信示意图

Qt:58---网络编程之TCP(QTcpServer、QTcpSocket)_服务端

  • 服务端程序使用QTcpServer用于端口监听,建立服务器
  • QTcpSocket用于建立连接后使用套接字进行通信



QT中所需模块

QT  +=network


二、QTcpServer

  • 头文件:#include <QTcpServer>
  • QTcpServer从QObject继承而来,主要用于服务器建立网络监听,创建网络Socket连接


主要函数与信号

Qt:58---网络编程之TCP(QTcpServer、QTcpSocket)_网络编程之TCP_02

  • listen():服务端使用该函数开启监听。参数1的IP地址可以是“127.0.0.1”或本机的实际IP或常量QHostAddress::LocalHost
  • incomingConnection():当有新的客户端接入时,该函数会创建一个与客户端连接的QTcpSocket对象,然后发射newConnection()信号。在newConnection()信号的糙汉书中,可以用nextPendingConnection()接受客户端的链接,然后使用QTcpSocket与客户端通信


三、QTcpSocket

  • 头文件:#include <QTcpSocket>
  • 客户端与服务器建立TCP连接后,具体的数据通信是通过QTcpSocket完成的。QTcpSocket提供了TCP协议的接口,可以使用QTcpSocket实现标准的网络通信协议如POP3、SMTP、NNTP


继承关系

  • QTcpSocket从QIODevice间接继承而来,所以具有流读写的功能

Qt:58---网络编程之TCP(QTcpServer、QTcpSocket)_服务端_03



主要函数与信号

  • QTcpSocket除了构造函数和析构函数。其他函数都是从QAbstractSocket继承或重定义的。QAbstractSocket用于TCP通信的主要接口函数如下

Qt:58---网络编程之TCP(QTcpServer、QTcpSocket)_服务端_04

  • readyRead()信号:​建立连接后,就可以向缓冲区读写数据,实现数据的通信,当缓冲区有新数据进入时,会发射readyRead()信号,一般在此信号的槽函数里读取缓冲区数据
  • stateChanged()信号:当当前socket状态改变时,触发该信号,参数为socket的状态枚举类型,取值如下

Qt:58---网络编程之TCP(QTcpServer、QTcpSocket)_网络编程之TCP_05

补充:

//常用函数
abort(); //中止当前连接并重置套接字。与disconnectFromHost()不同,该函数立即关闭套接字,丢弃写缓冲区中的任何挂起数据

write(); //向外界发送数据。参数:发送的内容(const char*或QByteArray型)
readAll(); //读取外界传入的所有数据,返回值:QByteArray型

waitForBytesWritten(); //写入多久,才执行后面的语句。参数:写入时间(毫秒单位),默认为3秒
waitForReadyRead(); //读取多久,才执行后面的语句。参数:读取时间(毫秒单位),默认为3秒

errorString(); //返回错误信息
isValid(); //判断套接字是否有效
isOpen(); //判断套接字是否打开
flush(); //刷新数据区

deleteLater(); //断开连接之后,可以调用该函数在稍后删除本次会话的socket

//信号函数
bytesWritten(qint64); //向外界发送数据成功后相应,参数为发送的字节数

  • setSocketOption()函数:​设置socket的选项特性



阻塞连接与非阻塞连接

  • connectToHost():​客户端的QTcpSocket实例通过connectToHost尝试连接服务区,该方式是异步连接,不会阻塞程序运行,连接后发生connection()信号
  • waitForConnected():​如果需要使用阻塞方式连接服务器,则使用该函数,程序会一直阻塞直到连接成功或失败


四、数据的传输


读取方式

Socket之间的数据通信协议一般有两种方式:

  • 基于行读:​每次读一行
  • 基于数据块读:​一般用于二进制数据的传输,需要自定义具体的格式

canReadLine()函数

  • 判断缓冲区中是否有一行数据可以读取,如果有,就调用readLine()函数读取一行的数据,例如:

Qt:58---网络编程之TCP(QTcpServer、QTcpSocket)_网络编程之TCP_06

如果基于二进制读:

数据的传输以QByteArray类型的形式传送(下面是QString与QByteArray类型的转换)

  • QByteArray转QString:1.QString强转  2.QString静态方法fromLocal8Bit
  • QString转QByteArray:1.QString函数:toUtf8();  2.QString函数:toLocal8Bit()



基本函数

  • 因为QTcpSocket是继承于QIODevice的,所以支持流的读写功能,也就支持流的读写函数

write(); //向外界发送数据

read(); //读取指定的数据
readLine(); //读取一行数据
readAll(); //读取外界传入的所有数据


五、演示案例