写在前面
基于TCP(传输控制协议)通信的原理涉及到两个主要角色:服务器和客户端。以下是基于TCP通信的简要原理:
- 服务器端: 服务器端首先创建一个QTcpServer对象,该对象负责监听指定的IP地址和端口,等待客户端的连接请求。 当有客户端连接请求到达时,服务器端会创建一个新的QTcpSocket对象,用于与该客户端建立通信通道。 通过QTcpSocket对象,服务器端和客户端可以进行双向的数据传输。
- 客户端: 客户端创建一个QTcpSocket对象,用于连接到服务器的指定IP地址和端口。 一旦连接建立,客户端可以通过该QTcpSocket对象向服务器端发送数据,并接收服务器端的响应数据。 客户端也可以监听来自服务器的数据,以实现双向通信。
- 数据传输: 数据在传输过程中会被拆分成小的数据包,每个数据包包含一部分信息。 TCP负责确保数据的可靠传输,通过序列号、确认应答、超时重传等机制来保证数据的完整性和顺序性。 在服务器和客户端之间建立的TCP连接是全双工的,允许双方同时进行读写操作。
- 连接的建立和断开: 在TCP通信中,连接的建立使用三次握手的过程,确保双方都能够正确收到对方的连接请求和确认。 连接的断开使用四次挥手的过程,确保双方都能够正确关闭连接。
服务器界面:
服务器代码:
#include "serverwindow.h"
#include "ui_serverwindow.h"
#include <QTime>
ServerWindow::ServerWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::ServerWindow)
{
ui->setupUi(this);
this->setWindowTitle("TCP服务器");
QLabel *label =new QLabel("连接状态:未连接");
this->ui->statusbar->addWidget(label);
//设置一个默认端口
this->ui->portlineEdit->setText("8088");
m_server = new QTcpServer(this); //初始化监听的服务器对象
//当服务器接收到新的连接时,获取新连接的套接字对象,接着使用QTcpSocket对象与客户端进行通信
connect(m_server, &QTcpServer::newConnection, this, [=](){
m_socket = m_server->nextPendingConnection();
qDebug()<<m_socket;
label->setText("连接状态:已连接");
//接收客户段信息
connect(m_socket, &QTcpSocket::readyRead, this, [=](){
QByteArray data= m_socket->readAll();
this->ui->recordTextEdit->append("客户端("+QTime::currentTime().toString()+"):"+data);
});
connect(m_socket, &QTcpSocket::disconnected, this, [=](){
m_socket->close();
delete m_socket;
label->setText("连接状态:未连接");
});
});
}
ServerWindow::~ServerWindow()
{
delete ui;
}
void ServerWindow::on_listenBtn_clicked()
{
//获取端口号
unsigned short port = this->ui->portlineEdit->text().toUShort();
//启动监听,将服务器绑定到本地的任意IP地址和指定的端口上。
this->m_server->listen(QHostAddress::Any, port);
this->ui->listenBtn->setDisabled(true);
}
void ServerWindow::on_sendMsgBtn_clicked()
{
QString msg = this->ui->msgTextEdit->toPlainText();
//将字节数组发送给服务器
this->m_socket->write(msg.toUtf8());
this->ui->recordTextEdit->append("服务器("+QTime::currentTime().toString()+"):"+msg);
this->ui->msgTextEdit->clear();
}
客户端界面:
客户端代码:
#include "clientwindow.h"
#include "ui_clientwindow.h"
#include <QHostAddress>
#include <QTime>
ClientWindow::ClientWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::ClientWindow)
{
ui->setupUi(this);
setWindowTitle("客户端");
QLabel *label =new QLabel("连接状态:未连接");
this->ui->statusbar->addWidget(label);
this->ui->portlineEdit->setText("8088"); //与服务器端口保持一致
this->ui->IPlineEdit->setText("127.0.0.1"); //本地ip
this->m_socket = new QTcpSocket(this); //初始化套接字对象
connect(m_socket, &QTcpSocket::readyRead, this, [=](){
QByteArray data = m_socket->readAll();
this->ui->recordTextEdit->append("服务器("+QTime::currentTime().toString()+"):"+data);
});
connect(m_socket, &QTcpSocket::disconnected, this, [=](){
this->m_socket->close();
//this->m_socket->deleteLater();
label->setText("连接状态:未连接");
this->ui->recordTextEdit->append("断开连接...");
});
connect(m_socket, &QTcpSocket::connected, this, [=](){
label->setText("连接状态:已连接");
this->ui->recordTextEdit->append("连接成功...");
});
}
ClientWindow::~ClientWindow()
{
delete ui;
}
void ClientWindow::on_ConnectBtn_clicked()
{
QString ip = this->ui->IPlineEdit->text();
unsigned short port = this->ui->portlineEdit->text().toUShort();
//连接到指定的主机和端口
m_socket->connectToHost(QHostAddress(ip),port);
}
void ClientWindow::on_sendMsgBtn_clicked()
{
QString msg = this->ui->SenMsgTextEdit->toPlainText();
m_socket->write(msg.toUtf8());
this->ui->recordTextEdit->append("客户端("+QTime::currentTime().toString()+"):"+msg);
this->ui->SenMsgTextEdit->clear();
}
void ClientWindow::on_DisConnectBtn_clicked()
{
this->m_socket->close();
}