🌟TCP协议概述
- 定义:传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 定义。
- 特点:
(1)基于流的方式;
(2)面向连接;
(3)可靠通信方式;
(4)在网络状况不佳的时候尽量降低系统由于重传带来的带宽开销;
(5)通信连接维护是面向通信的两个端点的,而不考虑中间网段和节点。 - 报文格式:

- 连接方式:
TCP建立连接前,需要进行三次握手,如下图所示:

- 对于握手时存在的报文丢失问题,TCP提供超时重传机制,通过计算报文往返时延以及报文的应答状态,来选择是否重新发送报文。
TCP断开连接前,需要进行四次挥手,如下图所示:

🌟Qt中TCP协议处理
- Qt中提供了QTcpSocket类和QTcpServer类分别用于创建TCP套接字和TCP服务器套接字。
💥QTcpSocket
- QTcpSocket类继承与QAbstractSocket,主要提供了socket套接字的创建、绑定端口、连接服务器等。

💥QTcpServer
- QTcpServer类继承于QSctpServer,主要提供了对于TCP连接信号的响应和监听等。

🌟Qt实现TCP通信
💥客户端
- 客户端是发送端,主要实现与服务器端建立连接、发送数据和接收数据。步骤如下:
建立TCP套接字 --> 连接服务器 --> 发送数据/接收数据
下面是客户端的源码:
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QObject>
#include <QTcpSocket>
#include <QHostAddress>
#include <QDebug>
#include <QTimer>
class TCPClient : QObject
{
Q_OBJECT
public:
TCPClient();
void InitSocket();
void InitTimer();
void ConnectToServer();
void SendData();
private:
QTcpSocket *mTcpSocket;
QHostAddress mServerAddress;
QTimer *mTimer;
};
#endif
#include "tcpclient.h"
TCPClient::TCPClient()
{
InitSocket();
ConnectToServer();
InitTimer();
}
void TCPClient::InitSocket()
{
mTcpSocket = new QTcpSocket;
mServerAddress.setAddress("10.0.0.177");
}
void TCPClient::InitTimer()
{
mTimer = new QTimer;
connect(mTimer,&QTimer::timeout,this,[=]
{
SendData();
});
mTimer->start(1000);
}
void TCPClient::ConnectToServer()
{
quint16 _port = 7777;
connect(mTcpSocket,&QTcpSocket::connected,this,[=]{
qDebug()<< "Connect To Server Successful!"<<endl;
});
mTcpSocket->connectToHost(mServerAddress,_port,QIODevice::WriteOnly);
}
void TCPClient::SendData()
{
QByteArray _data = "hello";
if(-1 != mTcpSocket->write(_data.data(),_data.length()))
{
qDebug()<< "TCP ==> Send data : "<< _data<<endl;
}
mTcpSocket->flush();
}
💥服务器端
- 服务器端是接收端,主要实现监听连接信号,建立连接、接收数据和发送数据。步骤如下:
建立监听套接字 --> 连接到客户端 --> 获得连接套接字 --> 接收数据/发送数据
下面是服务器端源码:
#ifndef TCPSEVER_H
#define TCPSEVER_H
#include <QObject>
#include <QHostAddress>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
class TCPSever : QObject
{
Q_OBJECT
public:
TCPSever();
void InitServer();
private:
QTcpServer *mTcpServer;
QTcpSocket *mTcpSocket;
QHostAddress mHostAddress;
};
#endif
#include "tcpsever.h"
TCPSever::TCPSever()
{
InitServer();
}
void TCPSever::InitServer()
{
mTcpServer = new QTcpServer(this);
mTcpSocket = new QTcpSocket;
mHostAddress.setAddress("10.0.0.177");
quint16 _port = 7777;
mTcpServer->listen(mHostAddress,_port);
qDebug()<<"Listen Interface ["<<mHostAddress.toString()<<"] And Port ["<<_port<<"] Successful!"<<endl;
connect(mTcpServer,&QTcpServer::newConnection,this,[=]{
mTcpSocket = mTcpServer->nextPendingConnection();
qDebug()<<"Connect To Client Successful!"<<endl;
connect(mTcpSocket,&QTcpSocket::readyRead,this,[=]{
QByteArray _data = mTcpSocket->readAll();
qDebug()<<"TCP Receive Data : "<<QString::fromLatin1(_data)<<endl;
});
});
}
🌟补充
- 以上只是一个简单的TCP测试demo,只能实现正常通信情况下的数据收发功能。
- 在正常的项目开发中,需要处理特殊场景下,TCP通信的应对方案。
- 有兴趣的读者,可以尝试在测试代码的基础上添加一些额外的模块,例如:连接存活检测以及自动重连机制、异步I/O和事件驱动模型、线程池和连接池处理等
- 后续我会逐步更写网络编程进阶的文章:)
